Table of Contents

  1. Notation
  2. Load and split the data
  3. Screening Questions
  4. Actual Survey Analysis
  5. Statistical Testing
  6. Skewed Data
  7. Decision-making

This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

plot(cars)

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.


README

Load and split the data

library(readr)
library(dplyr)
library(ggplot2)
library(tidyr)
library(FSA)
library(car)



exported_data <- read_csv("final_rawdata_value_1605.csv")
Rows: 332 Columns: 262── Column specification ─────────────────────────────────────────────────
Delimiter: ","
chr (262): StartDate, EndDate, Status, IPAddress, Progress, Duration ...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
exported_data <- subset(exported_data, select = -c(StartDate,EndDate,Status,IPAddress,Progress,Finished,RecordedDate, RecipientLastName,RecipientFirstName,                                  RecipientEmail,ExternalReference,LocationLatitude,LocationLongitude,DistributionChannel,UserLanguage))
rawdata_value <- subset(exported_data, select =-c(ResponseId,Q1.1,Q2.1))
rawdata_value <- rawdata_value[3:nrow(rawdata_value), ]

# label the group
rawdata_value <- rawdata_value %>%
  mutate(group = case_when(
    !is.na(Q4.2)  ~ '0-controlled',
    !is.na(Q6.2)  ~ '1-errorbar',
    !is.na(Q8.2)  ~ '2-shadedbar',
    !is.na(Q10.2) ~ '3-fanchartslice',
    !is.na(Q12.2) ~ '4-bellcurve'
  ))
# create a copy of the data for Q3.9 analysis
rawdata_q3_9 <- rawdata_value
# filter participants who do not understand the concept of inflation
rawdata_value <- rawdata_value[rawdata_value$Q3.9 == "4", ]

# rawdata_value <- rawdata_value %>%
#   mutate(group = case_when(
#     !is.na(Q4.2)  ~ 0,
#     !is.na(Q6.2)  ~ 1,
#     !is.na(Q8.2)  ~ 2,
#     !is.na(Q10.2) ~ 3,
#     !is.na(Q12.2) ~ 4
#   ))

# meta-data
total_respondents <- nrow(rawdata_value)


group_total <- rawdata_value %>%
  group_by(group) %>%
  summarise(n_respondents = n())

# total_treatment_respodents <- 
  
  
# graph preparation

likelihood_labels = c(
    "9" = "Exceptionally unlikely",
    "10" = "Very unlikely",
    "11" = "Quite unlikely",
    "12" = "Fifty-fifty",
    "13" = "Quite likely",
    "14" = "Very likely",
    "15" = "Virtually certain"
  )

# filter treatment groups
controlled_group <- rawdata_value[!is.na(rawdata_value$Q4.2), ]
error_bar <-rawdata_value[!is.na(rawdata_value$Q6.2), ]
shaded_bar <-rawdata_value[!is.na(rawdata_value$Q8.2), ]
fanchart_slice <-rawdata_value[!is.na(rawdata_value$Q10.2), ]
bell_curve <-rawdata_value[!is.na(rawdata_value$Q12.2), ]

# adding labels to the groups
# controlled_group$group <- 1
# error_bar$group <- 2
# shaded_bar$group <- 3
# fanchart_slice$group <- 4
# bell_curve$group <- 5


# remove unnecessary columns
controlled_group = controlled_group[,grepl("^(Q3|Q4|Q5)",names(controlled_group))|names(controlled_group) %in% c("Duration (in seconds)", "group")]
error_bar = error_bar[,grepl("^(Q3|Q6|Q7)",names(error_bar))| names(error_bar) %in% c("Duration (in seconds)", "group")]
shaded_bar = shaded_bar[,grepl("^(Q3|Q8|Q9)",names(shaded_bar))| names(shaded_bar)%in% c("Duration (in seconds)", "group")]
fanchart_slice = fanchart_slice[,grepl("^(Q3|Q10|Q11)",names(fanchart_slice))| names(fanchart_slice) %in% c("Duration (in seconds)", "group")]
bell_curve = bell_curve[,grepl("^(Q3|Q12|Q13)",names(bell_curve))| names(bell_curve) %in% c("Duration (in seconds)", "group")]
# controlled_group = controlled_group[,!sapply(controlled_group, function(x) mean(is.na(x)))>0.9]

group_list <- list(
  controlled = controlled_group,
  errorbar = error_bar,
  shadedbar = shaded_bar,
  fanchartslice = fanchart_slice,
  bellcurve = bell_curve
)

skewed_group_list <- group_list[-1]

Screening Questions

! Time Duration

Variable: continuous
Method: check normality + kruskal-wallis test + post-hoc test
Result: p< 0.05–> we can reject the hypothesis
controlled group is significantly different from (error bar; shaded bar; fanchart slice; BUT NOT fanchartslice)

time_duration_table <- rawdata_value[,c("Duration (in seconds)", "group")]
time_duration_table$`Duration (in mins)` <- as.numeric(time_duration_table$`Duration (in seconds)`)/60

# report quantile information
summary(time_duration_table$`Duration (in mins)`)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  4.117  13.967  19.883  22.524  27.133  85.233 
# test for normality --> It's definitely not normal distribution
# shapiro.test(time_duration_table$`Duration (in mins)`)

# run the kruskal-wallis test
kruskal_test <- kruskal.test(`Duration (in mins)` ~ group, data = time_duration_table)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  Duration (in mins) by group
Kruskal-Wallis chi-squared = 22.226, df = 4, p-value = 0.0001807
# run post-hoc test
dunn_test <- dunnTest(`Duration (in mins)` ~ group, data = time_duration_table, method = "bonferroni")
Warning: group was coerced to a factor.
print(dunn_test)
Dunn (1964) Kruskal-Wallis multiple comparison
  p-values adjusted with the Bonferroni method.

Time duration summary table

time_duration_summary <- time_duration_table %>%
  group_by(group) %>%
  summarise(mean_duration = mean(`Duration (in mins)`, na.rm = TRUE), 
            sd_duration = sd(`Duration (in mins)`, na.rm = TRUE),
            .groups = 'drop')

Plot the distribution of different groups

Plot time duration bar chart. It’s not valid as the data is not normal distribution.

ggplot(time_duration_summary, aes(x = group, y = mean_duration)) +
  geom_bar(stat = "identity", fill = "steelblue", width = 0.6) +
  geom_errorbar(aes(ymin = mean_duration - sd_duration, ymax = mean_duration + sd_duration), width = 0.2) +
  labs(title = "Response Duration by Group",
       y = "Duration (in minutes)",
       x = "Group") +
  theme_minimal()

Q3.2 Age

What is your age?
Variable: continuous
Method: kruskal-wallis test
Result: Fail to reject the null hypothesis

kruskal_test <- kruskal.test(`Q3.2` ~ group, data = age_table)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  Q3.2 by group
Kruskal-Wallis chi-squared = 2.5182, df = 4, p-value = 0.6414

Q3.3 Gender

Which of the following best describes your gender identity?
Variable: categorical
Method: contingency Table + chi-squared test
Result: Fail to reject the null hypothesis

q3_3_table <- rawdata_value[, c("Q3.3", "group")]
# q3_3_table$Q3.3 <- recode(q3_3_table$Q3.3,
#                                     "1" = "Male",
#                                     "2" = "Female",
#                                     .default = "Other")
q3_3_contingency <- table(q3_3_table$Q3.3, q3_3_table$group)
print(q3_3_contingency)
   
    bellcurve controlled errorbar fanchartslice shadedbar
  1        30         32       28            34        27
  2        32         33       31            29        35
  3         0          0        1             0         1
  4         0          0        1             0         0
# Chi-squared test
chisq.test(q3_3_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_3_contingency
X-squared = 8.6715, df = 12, p-value = 0.7307

Calculate the gender percentage

# percentage of male
male_per <- q3_3_contingency[1,]
gender_group_total <- colSums(q3_3_contingency)
male_prop <- male_per/gender_group_total

Q3.4 Highest Education

What is your highest level of education achieved?
Variable: categorical with written insights from choice 9 Method: contingency Table + chi-squared test
Result: Fail to reject the null hypothesis

q3_4_table <- rawdata_value[rawdata_value$`Q3.4` != "9", c("Q3.4", "group")]

q3_4_contingency <- table(q3_4_table$Q3.4, q3_4_table$group)
# Chi-squared test
chisq.test(q3_4_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_4_contingency
X-squared = 19.937, df = 28, p-value = 0.8667

Highest Education Level proportion bar plot across different groups


q3_4_prop  <- as.data.frame(q3_4_contingency)
# rename columns
names(q3_4_prop) <- c("Q3.4", "Group", "Count")

# calculate proportions within each group
q3_4_prop <- q3_4_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))

ggplot(q3_4_prop, aes(x = as.factor(`Q3.4`), y = Proportion, fill = Group)) +
  geom_bar(stat = "identity", position = "dodge") +
  facet_wrap(~ Group) +
  labs(
    title = "Q3.4 Highest Education Level Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
  # scale_x_discrete(labels = c(
  #   "1" = "No formal education",
  #   "2" = "Primary/Elementary",
  #   "3" = "Secondary School (GCSE)",
  #   "4" = "High School (A Level)",
  #   "5" = "Technical or Vocational",
  #   "6" = "Bachelors or equivalent degree level qualification",
  #   "7" = "Masters or equivalent higher degree level qualification",
  #   "8" = "PhD or equivalent doctoral level qualification"))+
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_4_table <- rawdata_value[, c("Q3.4", "group")]

# Q3.4 summary table
q3_4_summary <- q3_4_table %>%
  group_by(`Q3.4`) %>%
  summarise(count = n()) %>%
  mutate(proportion = count / sum(count),
         label = 
            case_when(
              Q3.4 == "1" ~ "1-No formal education",
              Q3.4 == "2" ~ "2-Primary/Elementary",
              Q3.4 == "3" ~ "3-Secondary School (GCSE)",
              Q3.4 == "4" ~ "4-High School (A Level)",
              Q3.4 == "5" ~ "5-Technical or Vocational",
              Q3.4 == "6" ~ "6-Bachelors or equivalent degree level qualification",
              Q3.4 == "7" ~ "7-Masters or equivalent higher degree level qualification",
              Q3.4 == "8" ~ "8-PhD or equivalent doctoral level qualification",
              Q3.4 == "9" ~ "9-Other"
            ),
         label = paste0(label, " (", round(proportion * 100, 2), " %)")
         )

ggplot(q3_4_summary, aes(x = "",y = proportion, fill = label)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.4 Highest Education Level Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.5 Employee Status

What is your current profession or employment status?
Variable: categorical
Method: contingency Table + chi-squared test
Result: Fail to reject the null hypothesis

q3_5_table <- rawdata_value[rawdata_value$`Q3.5` != "6", c("Q3.5", "group")]
q3_5_contingency <- table(q3_5_table$Q3.5, q3_5_table$group)
# print(q3_5_contingency)

# Chi-squared test
chisq.test(q3_5_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_5_contingency
X-squared = 17.324, df = 16, p-value = 0.3649

Employee status proportion bar plot across different groups

q3_5_prop  <- as.data.frame(q3_5_contingency)
# rename columns
names(q3_5_prop) <- c("Q3.5", "Group", "Count")


# calculate proportions within each group
q3_5_prop <- q3_5_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))

ggplot(q3_5_prop, aes(x = as.factor(`Q3.5`), y = Proportion, fill = Group)) +
  geom_bar(stat = "identity", position = "dodge") +
  # facet_wrap(~ Group) +
  labs(
    title = "Q3.5 Employee Status Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
  scale_x_discrete(labels = c(
    "1" = "Student",
    "2" = "Employed",
    "3" = "Self-employed",
    "4" = "Retired",
    "5" = "Unemployed"
  )) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_5_table <- rawdata_value[, c("Q3.5", "group")]
q3_5_summary <- q3_5_table %>%
  group_by(`Q3.5`) %>%
  summarise(count = n()) %>%
  mutate(proportion = count / sum(count),
         label = 
            case_when(
              Q3.5 == "1" ~ "1-Student",
              Q3.5 == "2" ~ "2-Employed",
              Q3.5 == "3" ~ "3-Self-employed",
              Q3.5 == "4" ~ "4-Retired",
              Q3.5 == "5" ~ "5-Unemployed",
              Q3.5 == "6" ~ "6-Other"
            ),
         label = paste0(label, " (", round(proportion * 100, 2), " %)")
         )
ggplot(q3_5_summary, aes(x = "",y = proportion, fill = label)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.5 Employee Status Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.6 Economics Education

In which, if any, have you ever studied economics? (Select all that apply)
Variable: categorical
Method: convert to list and count + chi-squared test
Result: Fail to reject the null hypothesis

Plot percentage bar chart including all participants

q3_6_table <- rawdata_value[, c("Q3.6", "group")]
q3_6_table$Q3.6 <- lapply(q3_6_table$Q3.6, function(x) as.list(as.numeric(strsplit(x, ",")[[1]])))

# count the number of occurrences of each value
q3_6_summary <- q3_6_table %>%
  unnest(Q3.6) %>%
  group_by(`Q3.6`) %>%
  summarise(count = n()) %>%
  mutate(proportion = count / total_respondents,
         label = 
            case_when(
              Q3.6 == "1" ~ "1-At school",
              Q3.6 == "2" ~ "2-In higher education",
              Q3.6 == "3" ~ "3-Through self-directed study",
              Q3.6 == "4" ~ "4-Self-motivated study",
              Q3.6 == "5" ~ "5-Never studied economics",
              Q3.6 == "6" ~ "6-Don’t know / can’t recall",
              Q3.6 == "7" ~ "7-Other"
            ))

# q3_6_summary$Q3.6 <- as.numeric(q3_6_summary$Q3.6)
ggplot(q3_6_summary, aes(x = factor(label), y = proportion)) +
  geom_col(fill = "steelblue") +
  geom_text(aes(label = paste0(round(proportion * 100, 1), "%")), 
            vjust = -0.3, size = 3.5) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(
    title = "Percentage of Participants Selecting Each Q3.6 Option",
    x = "Response",
    y = "Percentage of Participants"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

q3_6_table <- rawdata_value[, c("Q3.6", "group")]
q3_6_table$Q3.6 <- lapply(q3_6_table$Q3.6, function(x) as.list(as.numeric(strsplit(x, ",")[[1]])))
# count the number of occurrences of each value
q3_6_prop <- q3_6_table %>%
  unnest(Q3.6) %>%
  group_by(group, Q3.6) %>%
  summarise(count = n(), .groups = 'drop')
q3_6_prop$Q3.6 <- as.numeric(q3_6_prop$Q3.6)

# create a contingency table
q3_6_contingency <- xtabs(count ~ Q3.6 + group, data = q3_6_prop)
print(q3_6_contingency)
    group
Q3.6 0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
   1           12         20          13              16          21
   2            8         10          17              18          11
   3            4          8           8               7           5
   4            4          6           5               8           5
   5           36         28          28              28          26
   6            2          0           1               1           1
   7            0          2           0               0           1
# Chi-squared test
chisq.test(q3_6_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_6_contingency
X-squared = 22.428, df = 24, p-value = 0.5537
# q3_6_test <-q3_6_prop %>%
#   group_by(`Q3.6`) %>%
#   summarise(total_count = sum(count), .groups = "drop")

Economics Education proportion bar plot across different groups

# convert contingency table to data frame # count 0 as well
q3_6_prop <- as.data.frame(q3_6_contingency)
# calculate proportions within each group
q3_6_prop <- q3_6_prop %>%
  left_join(group_total, by = "group") %>%
  mutate(Proportion = Freq / n_respondents)

ggplot(q3_6_prop, aes(x = factor(Q3.6), y = Proportion, fill = factor(group))) +
  geom_col(position = "dodge") +
  labs(
    title = "Q3.6 Economics Education Propotion Plot across Groups",
    x = "Response",
    y = "Proportion",
    fill = "Group"
  ) +
  scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()

Q3.7 Financial Activities

Which of the following financial activities do you actively participate in? (Select all that apply) - Selected Choice Fixed Income (e.g., government bonds, corporate bonds)
Variable: categorical
Method: convert to list and count + chi-squared test
Result: Fail to reject the null hypothesis

q3_7_table <- rawdata_value[, c("Q3.7", "group")]
q3_7_table$Q3.7 <- lapply(q3_7_table$Q3.7, function(x) as.list(as.numeric(strsplit(x, ",")[[1]])))
# count the number of occurrences of each value in each group
q3_7_prop <- q3_7_table %>%
  unnest(Q3.7) %>%
  group_by(group,`Q3.7`) %>%
  summarise(count = n(), .groups = 'drop')
q3_7_prop$Q3.7 <- as.numeric(q3_7_prop$Q3.7)

# create a contingency table
q3_7_contingency <- xtabs(count ~ `Q3.7` + group, data = q3_7_prop)
print(q3_7_contingency)
    group
Q3.7 0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  11           49         53          51              59          48
  12           25         32          29              33          26
  13            9         16           8               7          10
  14           29         35          31              25          29
  15            3         13           5               9           4
  16            1          8           2               6           6
  17            9         14          13              12           9
  18            4          4           5               2           7
  19            1          2           0               0           0
# Chi-squared test
chisq.test(q3_7_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_7_contingency
X-squared = 28.26, df = 32, p-value = 0.6564

Plot financial activities proportion bar plot across different groups

# convert contingency table to data frame
q3_7_prop <- as.data.frame(q3_7_contingency) %>%
  left_join(group_total, by = "group") %>%
  mutate(Proportion = Freq / n_respondents)


ggplot(q3_7_prop, aes(x = factor(`Q3.7`), y = Proportion, fill = factor(group))) + 
  geom_col(position = "dodge") +
  labs(
    title = "Q3.7 Financial Activities Propotion Plot across Groups",
    x = "Response",
    y = "Proportion",
    fill = "Group"
  ) +
    scale_x_discrete(labels = c(
    "11" = "Savings",
    "12" = "Investments",
    "13" = "Fixed Income",
    "14" = "Retirement Planning",
    "15" = "Trading",
    "16" = "Real Estate",
    "17" = "Cryptocurrencies",
    "18" = "None of the above",
    "19" = "Other"
      )) +
  scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot percentage bar chart including all participants

q3_7_summary <-q3_7_prop %>%
  group_by(`Q3.7`) %>%
  summarise(total_count = sum(Freq), .groups = "drop") %>%
  mutate(proportion = total_count / total_respondents,
         label = 
            case_when(
              `Q3.7` == "11" ~ "11-Savings",
              `Q3.7` == "12" ~ "12-Investments",
              `Q3.7` == "13" ~ "13-Fixed Income",
              `Q3.7` == "14" ~ "14-Retirement Planning",
              `Q3.7` == "15" ~ "15-Trading",
              `Q3.7` == "16" ~ "16-Real Estate",
              `Q3.7` == "17" ~ "17-Cryptocurrencies",
              `Q3.7` == "18" ~ "18-None of the above",
              `Q3.7` == "19" ~ "19-Other"
            ))

ggplot(q3_7_summary, aes(x = factor(label), y = proportion)) +
  geom_col(fill = "steelblue") +
  geom_text(aes(label = paste0(round(proportion * 100, 1), "%")), 
            vjust = -0.3, size = 3.5) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(
    title = "Percentage of Participants Selecting Each Q3.7 Option",
    x = "Response",
    y = "Percentage of Participants"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Q3.8 Awareness of Economics

How frequently, if at all, do you read/watch/listen to news stories related to economics or the economy?
Variable: categorical
Method: contingency table + chi-squared test
Result: Fail to reject the null hypothesis

chisq.test(q3_8_contingency[-nrow(q3_8_contingency), ])
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_8_contingency[-nrow(q3_8_contingency), ]
X-squared = 30.527, df = 20, p-value = 0.06175

Awareness of Economics proportion bar plot across different groups

q3_8_prop  <- as.data.frame(q3_8_contingency)
# rename columns
names(q3_8_prop) <- c("Q3.8", "Group", "Count")

# add a labelled column
q3_8_prop <- q3_8_prop %>%
  mutate(Q3.8_label = case_when(
    Q3.8 == "1" ~ "1-Never",
    Q3.8 == "2" ~ "2-Rarely",
    Q3.8 == "3" ~ "3-Monthly",
    Q3.8 == "4" ~ "4-Weekly",
    Q3.8 == "5" ~ "5-Almost daily",
    Q3.8 == "6" ~ "6-Every day",
    Q3.8 == "7" ~ "7-Not sure"
  ))

# calculate proportions within each group
q3_8_prop <- q3_8_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))

ggplot(q3_8_prop, aes(x = as.factor(`Q3.8_label`), y = Proportion, fill = Group)) +
  geom_col(position = "dodge") +
  # facet_wrap(~ Group) +
  labs(
    title = "Q3.8 Awareness of Economics Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_8_summary <- q3_8_prop %>%
  group_by(`Q3.8_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
        `Q3.8_label` = paste0(`Q3.8_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(q3_8_summary, aes(x = "",y = proportion, fill = `Q3.8_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.8 Awareness of Economics Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.9 Inflation Knowledge

To the best of your knowledge, which option most accurately describes what inflation is?
Definitive correct answer
Variable: categorical
Method: descriptive analysis
Respondents were filtered based on whether if they can understand what inflation is.

q3_9_table <- rawdata_q3_9[, c("Q3.9", "group")]
q3_9_summary <- q3_9_table %>%
  group_by(`Q3.9`) %>%
  summarise(count = n()) %>%
  mutate(proportion = count / sum(count))

  ggplot(q3_9_summary, aes(x = "",y = proportion, fill = `Q3.9`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.9 Inflation Knowledge Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.11 Trust of Official Data

How much do you trust official inflation forecasts (For instance, the forecasts released by the Bank of England)?
ascending value-increasing trust + exclude 6- Unsure / no opinion
Variable: treat as continuous
Method: Kruskal-Wallis test
Result: Fail to reject the null hypothesis

q3_11_table <- rawdata_value[rawdata_value$`Q3.11` != "6", c("Q3.11", "group")]
q3_11_table$Q3.11 <- as.numeric(q3_11_table$`Q3.11`)
# check normality --> Not normally distributed
# shapiro.test(q3_11_table$Q3.11)
# bartlett.test(`Q3.11` ~ group, data = q3_11_table)


# run kruskal test
kruskal_test <- kruskal.test(Q3.11 ~ group, data = q3_11_table)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  Q3.11 by group
Kruskal-Wallis chi-squared = 3.4585, df = 4, p-value = 0.4842
q3_11_summary <- q3_11_table %>%
  group_by(group) %>%
  summarise(q3_11_mean = mean(as.numeric(Q3.11), na.rm = TRUE),
            q3_11_sd = sd(as.numeric(Q3.11), na.rm = TRUE),
            .groups = 'drop')

# report quantile information
summary(q3_11_table$Q3.11)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   3.000   4.000   3.711   4.000   5.000 

Plot the distribution of different groups

# histogram including all participants
ggplot(q3_11_table, aes(x = Q3.11)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Q3.11 Trust official inflation forecasts distribution",
       x = "Q3.11",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(q3_11_table$Q3.11, na.rm = TRUE), by = 1)) +
  theme_minimal()


# Grouped bar-style histogram
ggplot(q3_11_table, aes(x = factor(Q3.11), fill = factor(group))) +
  geom_bar(position = "dodge") +
  labs(
    title = "Q3.11 Trust official inflation forecasts distribution by group",
    x = "Q3.11 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

Q3.12 Frequency of Checking Current Inflation

How often do you check the current value of inflation? Variable: categorical
Method: contingency table + chi-squared test
Result: Fail to reject the null hypothesis

# Initial Check
summary(as.numeric(rawdata_value$Q3.12))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   2.000   2.392   3.000   4.000 
q3_12_table <- rawdata_value[, c("Q3.12", "group")]
q3_12_contingency <- table(q3_12_table$Q3.12, q3_12_table$group)
print(q3_12_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            6          5          10               7           6
  2           30         24          27              20          27
  3           16         25          21              29          22
  4            4          5           2               5           2
# Chi-squared test
chisq.test(q3_12_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_12_contingency
X-squared = 10.744, df = 12, p-value = 0.5509

Frequency of Checking Current Inflation proportion bar plot across different groups

q3_12_prop  <- as.data.frame(q3_12_contingency)
# rename columns
names(q3_12_prop) <- c("Q3.12", "Group", "Count")

# add a labelled column
q3_12_prop <- q3_12_prop %>%
  mutate(Q3.12_label = case_when(
    Q3.12 == "1" ~ "1-Never",
    Q3.12 == "2" ~ "2-Rarely",
    Q3.12 == "3" ~ "3-Sometimes",
    Q3.12 == "4" ~ "4-Often"
  ))
# calculate proportions within each group
q3_12_prop <- q3_12_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))

ggplot(q3_12_prop, aes(x = as.factor(`Q3.12_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q3.12 Frequency of Checking Current Inflation Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

NA

Plot pie chart including all participants

q3_12_summary <- q3_12_prop %>%
  group_by(`Q3.12_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `Q3.12_label` = paste0(`Q3.12_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(q3_12_summary, aes(x = "",y = proportion, fill = `Q3.12_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.12 Frequency of Checking Current Inflation Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.13 Source of Current Inflation

Which source do you rely on to inform yourself about the current value of inflation?
Variable: categorical
Method: convert to list and count + chi-squared test
Result: Fail to reject the null hypothesis

q3_13_table <- rawdata_value[, c("Q3.13", "group")]
q3_13_table$Q3.13 <- lapply(q3_13_table$Q3.13, function(x) as.list(as.numeric(strsplit(x, ",")[[1]])))
# count the number of occurrences of each value
q3_13_prop <- q3_13_table %>%
  unnest(Q3.13) %>%
  group_by(group,`Q3.13`) %>%
  summarise(count = n(), .groups = 'drop')
q3_13_prop$Q3.13 <- as.numeric(q3_13_prop$Q3.13)
# create a contingency table
q3_13_contingency <- xtabs(count ~ `Q3.13` + group, data = q3_13_prop)
print(q3_13_contingency)
     group
Q3.13 0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
    1           43         41          33              44          36
    2           16         16          15              13          16
    3           24         28          26              29          21
    4            5          7           8               4          10
    5           15         15          22              21          17
    6            6          6           7               4          11
    7           15         13          15              19          13
    8            5          8           5               5           1
    9            2          0           0               0           0
# Chi-squared test
chisq.test(q3_13_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_13_contingency
X-squared = 28.283, df = 32, p-value = 0.6553

Plot source of current inflation proportion bar plot across different groups

# convert contingency table to data frame
q3_13_prop <- as.data.frame(q3_13_contingency) %>%
  left_join(group_total, by = "group") %>%
  mutate(Proportion = Freq / n_respondents)

# add a labelled column
q3_13_prop <- q3_13_prop %>%
  mutate(Q3.13_label = case_when(
    `Q3.13` == "1" ~ "1-Television, radio or print media",
    `Q3.13` == "2" ~ "2-Social media",
    `Q3.13` == "3" ~ "3-Official websites or data releases",
    `Q3.13` == "4" ~ "4-Content platform",
    `Q3.13` == "5" ~ "5-Actively search on search engines",
    `Q3.13` == "6" ~ "6-Family or friends",
    `Q3.13` == "7" ~ "7-Financial advice websites/forums",
    `Q3.13` == "8" ~ "8-Private banks or economic research institutes",
    `Q3.13` == "9" ~ "9-Other"
  ))
ggplot(q3_13_prop, aes(x = factor(`Q3.13_label`), y = Proportion, fill = group)) +
  geom_col(position = "dodge") +
  labs(
    title = "Q3.13 Source of Current Inflation Propotion Plot across Groups",
    x = "Response",
    y = "Proportion",
    fill = "Group"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot percentage bar chart including all participants

q3_13_summary <- q3_13_prop %>%
  group_by(`Q3.13_label`) %>%
  summarise(total_count = sum(Freq), .groups = "drop") %>%
  mutate(proportion = total_count / total_respondents)

ggplot(q3_13_summary, aes(x = factor(Q3.13_label), y = proportion)) +
  geom_col(fill = "steelblue") +
  geom_text(aes(label = paste0(round(proportion * 100, 1), "%")), 
            vjust = -0.3, size = 3.5) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(
    title = "Percentage of Participants Selecting Each Q3.13 Option",
    x = "Response",
    y = "Percentage of Participants"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Q3.14 Impact of Current Inflation

To what extent do you feel that the current value of inflation is impacting your personal finances? Variable: categorical
Method: contingency table + chi-squared test
Result: Fail to reject the null hypothesis

# Initial Check
summary(as.numeric(rawdata_value$Q3.14))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   3.000   2.826   3.000   4.000 
q3_14_table <- rawdata_value[, c("Q3.14", "group")]
q3_14_contingency <- table(q3_14_table$Q3.14, q3_14_table$group)
print(q3_14_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            3          0           4               0           1
  2           22         18          19              19          18
  3           22         30          25              28          23
  4            9         11          12              14          15
# Chi-squared test
chisq.test(q3_14_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_14_contingency
X-squared = 12.14, df = 12, p-value = 0.4345

Impact of Current Inflation proportion bar plot across different groups

q3_14_prop  <- as.data.frame(q3_14_contingency)
# rename columns
names(q3_14_prop) <- c("Q3.14", "Group", "Count")
# add a labelled column
q3_14_prop <- q3_14_prop %>%
  mutate(Q3.14_label = case_when(
    Q3.14 == "1" ~ "1-Not at all",
    Q3.14 == "2" ~ "2-Slightly",
    Q3.14 == "3" ~ "3-Moderately",
    Q3.14 == "4" ~ "4-Very significantly"
  ))
# calculate proportions within each group
q3_14_prop <- q3_14_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(q3_14_prop, aes(x = as.factor(`Q3.14_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q3.14 Impact of Current Inflation Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_14_summary <- q3_14_prop %>%
  group_by(`Q3.14_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
        `Q3.14_label` = paste0(`Q3.14_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(q3_14_summary, aes(x = "",y = proportion, fill = `Q3.14_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.14 Impact of Current Inflation Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.15 Response to Current Inflation

How much do you adjust or take action in response to the change in current value of inflation?
Variable: categorical
Method: contingency table + chi-squared test
Result: Fail to reject the null hypothesis

# Initial Check
summary(as.numeric(rawdata_value$Q3.15))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   3.000   2.519   3.000   4.000 
q3_15_table <- rawdata_value[, c("Q3.15", "group")]
q3_15_contingency <- table(q3_15_table$Q3.15, q3_15_table$group)
print(q3_15_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            8          2           8               9           7
  2           25         20          22              14          20
  3           18         29          23              34          26
  4            5          8           7               4           4
# Chi-squared test
chisq.test(q3_15_contingency)

    Pearson's Chi-squared test

data:  q3_15_contingency
X-squared = 15.333, df = 12, p-value = 0.2237

Response to Current Inflation proportion bar plot across different groups

q3_15_prop  <- as.data.frame(q3_15_contingency)
# rename columns
names(q3_15_prop) <- c("Q3.15", "Group", "Count")
# add a labelled column
q3_15_prop <- q3_15_prop %>%
  mutate(Q3.15_label = case_when(
    Q3.15 == "1" ~ "1-Not at all",
    Q3.15 == "2" ~ "2-Rarely",
    Q3.15 == "3" ~ "3-Somewhat actively",
    Q3.15 == "4" ~ "4-Very actively"
  ))
# calculate proportions within each group
q3_15_prop <- q3_15_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(q3_15_prop, aes(x = as.factor(`Q3.15_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q3.15 Response to Current Inflation Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_15_summary <- q3_15_prop %>%
  group_by(`Q3.15_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `Q3.15_graph_label` = paste0(`Q3.15_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(q3_15_summary, aes(x = "",y = proportion, fill = `Q3.15_graph_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.15 Response to Current Inflation Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.16 Frequency of Checking Inflation Forecasts

How often do you look at inflation forecasts (that is, information about future inflation)?
Variable: categorical
Method: contingency table + chi-squared test
Result: Fail to reject the null hypothesis

# Initial Check
summary(as.numeric(rawdata_value$Q3.16))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   2.000   2.167   3.000   4.000 
q3_16_table <- rawdata_value[, c("Q3.16", "group")]
q3_16_contingency <- table(q3_16_table$Q3.16, q3_16_table$group)
print(q3_16_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            9         14          15              12           9
  2           35         23          23              27          32
  3            7         19          20              18          16
  4            5          3           2               4           0
# Chi-squared test
chisq.test(q3_16_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_16_contingency
X-squared = 19.045, df = 12, p-value = 0.08745

Frequency of Checking Inflation Forecasts proportion bar plot across different groups

q3_16_prop  <- as.data.frame(q3_16_contingency)
# rename columns
names(q3_16_prop) <- c("Q3.16", "Group", "Count")
# add a labelled column
q3_16_prop <- q3_16_prop %>%
  mutate(Q3.16_label = case_when(
    Q3.16 == "1" ~ "1-Never",
    Q3.16 == "2" ~ "2-Rarely",
    Q3.16 == "3" ~ "3-Sometimes",
    Q3.16 == "4" ~ "4-Often"
  ))
# calculate proportions within each group
q3_16_prop <- q3_16_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(q3_16_prop, aes(x = as.factor(`Q3.16_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q3.16 Frequency of Checking Inflation Forecasts Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_16_summary <- q3_16_prop %>%
  group_by(`Q3.16_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `Q3.16_label` = paste0(`Q3.16_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(q3_16_summary, aes(x = "",y = proportion, fill = `Q3.16_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.16 Frequency of Checking Inflation Forecasts Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.17 Source of Inflation Forecasts

Which source do you rely on to obtain inflation forecasts (information about future inflation)?
Variable: categorical
Method: convert to list and count + chi-squared test
Result: Fail to reject the null hypothesis

q3_17_table <- rawdata_value[, c("Q3.17", "group")]
q3_17_table$Q3.17 <- lapply(q3_17_table$Q3.17, function(x) as.list(as.numeric(strsplit(x, ",")[[1]])))
# count the number of occurrences of each value
q3_17_prop <- q3_17_table %>%
  unnest(Q3.17) %>%
  group_by(group,`Q3.17`) %>%
  summarise(count = n(), .groups = 'drop')
q3_17_prop$Q3.17 <- as.numeric(q3_17_prop$Q3.17)
# create a contingency table
q3_17_contingency <- xtabs(count ~ `Q3.17` + group, data = q3_17_prop)
print(q3_17_contingency)
     group
Q3.17 0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
    1           35         31          34              31          31
    2           13         16          13              11          12
    3           15         21          22              24          25
    4            4          9           8               4           6
    5           14         17          19              16          14
    6            4          4           6               3           6
    7           13         15          16              17          15
    8            3          9           4               5           2
    9            2          0           0               0           0
# Chi-squared test
chisq.test(q3_17_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  q3_17_contingency
X-squared = 23.655, df = 32, p-value = 0.8566

Plot source of inflation forecasts proportion bar plot across different groups

# convert contingency table to data frame
q3_17_prop <- as.data.frame(q3_17_contingency) %>%
  left_join(group_total, by = "group") %>%
  mutate(Proportion = Freq / n_respondents)
# add a labelled column
q3_17_prop <- q3_17_prop %>%
  mutate(Q3.17_label = case_when(
    `Q3.17` == "1" ~ "1-Television, radio or print media",
    `Q3.17` == "2" ~ "2-Social media",
    `Q3.17` == "3" ~ "3-Official websites or data releases",
    `Q3.17` == "4" ~ "4-Content platform",
    `Q3.17` == "5" ~ "5-Actively search on search engines",
    `Q3.17` == "6" ~ "6-Family or friends",
    `Q3.17` == "7" ~ "7-Financial advice websites/forums",
    `Q3.17` == "8" ~ "8-Private banks or economic research institutes",
    `Q3.17` == "9" ~ "9-Other"
  ))
ggplot(q3_17_prop, aes(x = factor(`Q3.17_label`), y = Proportion, fill = group)) +
  geom_col(position = "dodge") +
  labs(
    title = "Q3.17 Source of Inflation Forecasts Propotion Plot across Groups",
    x = "Response",
    y = "Proportion",
    fill = "Group"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot percentage bar chart including all participants

q3_17_summary <- q3_17_prop %>%
  group_by(`Q3.17_label`) %>%
  summarise(total_count = sum(Freq), .groups = "drop") %>%
  mutate(proportion = total_count / total_respondents)
ggplot(q3_17_summary, aes(x = factor(Q3.17_label), y = proportion)) +
  geom_col(fill = "steelblue") +
  geom_text(aes(label = paste0(round(proportion * 100, 1), "%")), 
            vjust = -0.3, size = 3.5) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(
    title = "Percentage of Participants Selecting Each Q3.17 Option",
    x = "Response",
    y = "Percentage of Participants"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Q3.18 Impact of Inflation Forecasts

To what extent do you feel that inflation forecasts (information about future inflation) impact your personal finances?
Variable: categorical
Method: contingency table + chi-squared test
Result: Fail to reject the null hypothesis

# Initial Check
summary(as.numeric(rawdata_value$Q3.18))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   2.000   2.321   3.000   4.000 
q3_18_table <- rawdata_value[, c("Q3.18", "group")]
q3_18_contingency <- table(q3_18_table$Q3.18, q3_18_table$group)
print(q3_18_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1           13          9          15               7           9
  2           22         29          17              29          24
  3           17         14          22              20          18
  4            4          7           6               5           6
# Chi-squared test
chisq.test(q3_18_contingency)

    Pearson's Chi-squared test

data:  q3_18_contingency
X-squared = 10.822, df = 12, p-value = 0.5443

Impact of Inflation Forecasts proportion bar plot across different groups

q3_18_prop  <- as.data.frame(q3_18_contingency)
# rename columns
names(q3_18_prop) <- c("Q3.18", "Group", "Count")
# add a labelled column
q3_18_prop <- q3_18_prop %>%
  mutate(Q3.18_label = case_when(
    Q3.18 == "1" ~ "1-Not at all",
    Q3.18 == "2" ~ "2-Slightly",
    Q3.18 == "3" ~ "3-Moderately",
    Q3.18 == "4" ~ "4-Very significantly"
  ))
# calculate proportions within each group
q3_18_prop <- q3_18_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(q3_18_prop, aes(x = as.factor(`Q3.18_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q3.18 Impact of Inflation Forecasts Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_18_summary <- q3_18_prop %>%
  group_by(`Q3.18_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `Q3.18_label` = paste0(`Q3.18_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(q3_18_summary, aes(x = "",y = proportion, fill = `Q3.18_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.18 Impact of Inflation Forecasts Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Q3.19 Response to Inflation Forecasts

How much do you adjust or take action in response to inflation forecasts (information about future inflation)?
Variable: categorical
Method: contingency table + chi-squared test
Result: Fail to reject the null hypothesis

# Initial Check
summary(as.numeric(rawdata_value$Q3.19))
q3_19_table <- rawdata_value[, c("Q3.19", "group")]
q3_19_contingency <- table(q3_19_table$Q3.19, q3_19_table$group)
print(q3_19_contingency)
# Chi-squared test
chisq.test(q3_19_contingency)

Response to Inflation Forecasts proportion bar plot across different groups

q3_19_prop  <- as.data.frame(q3_19_contingency)
# rename columns
names(q3_19_prop) <- c("Q3.19", "Group", "Count")
# add a labelled column
q3_19_prop <- q3_19_prop %>%
  mutate(Q3.19_label = case_when(
    Q3.19 == "1" ~ "1-Not at all",
    Q3.19 == "2" ~ "2-Rarely",
    Q3.19 == "3" ~ "3-Somewhat actively",
    Q3.19 == "4" ~ "4-Very actively"
  ))
# calculate proportions within each group
q3_19_prop <- q3_19_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(q3_19_prop, aes(x = as.factor(`Q3.19_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q3.19 Response to Inflation Forecasts Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

q3_19_summary <- q3_19_prop %>%
  group_by(`Q3.19_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `Q3.19_graph_label` = paste0(`Q3.19_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(q3_19_summary, aes(x = "",y = proportion, fill = `Q3.19_graph_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.19 Response to Inflation Forecasts Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Actual Survey Analysis

! Qxx.2 Graph Familarity

Have you ever been communicated this type of information before?
Variable: categorical
Method: Contingency Table + Chi-squared test
recode to yes and no
Result: We can reject the null hypothesis, meaning people are more or less familiar with certain type of visualisations.

chisq_result <- chisq.test(survey_q2_contingency)
chisq_result$stdres  
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  N    -1.588275  -0.909674    2.477879        1.397084   -1.459834
  Y     1.588275   0.909674   -2.477879       -1.397084    1.459834

Summary Table of proportion of yes and no

yes_per <- survey_q2_contingency[2,]
no_per <- survey_q2_contingency[1,]
familarity_group_total <- colSums(survey_q2_contingency)
yes_prop <- yes_per/familarity_group_total
no_prop <- no_per/familarity_group_total
# convert to data frame
survey_q2_summary <-data.frame(yes_prop, no_prop)

Plot the graph

ggplot(survey_q2, aes(x = q2_recode, fill = group)) +
  geom_bar(position = "dodge") +
  labs(title = "Have you ever been communicated this type of information before?",
       x = "Response",
       y = "Count") +
  scale_fill_brewer(palette = "Set2") +
  theme_minimal()

Qxx.3 Prior Expectation

Does the inflation forecast information provided align with your expectations?
Variable: categorical
Method: Contingency Table + Chi-squared test
Result: Fail to reject the null hypothesis

# combine data from different groups
survey_q3 <- data.frame()
survey_q3_list <- list("Q4.3","Q6.3", "Q8.3", "Q10.3", "Q12.3")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q3_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q3_value", "group")
  survey_q3 <- rbind(survey_q3, temp_table)
}

# Initial Check
summary(as.numeric(survey_q3$q3_value))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   2.000   2.476   3.000   5.000 

Test the differences between groups

survey_q3_contingency <- table(survey_q3$q3_value, survey_q3$group)
# print the contingency table
print(survey_q3_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            4          3           1               1           4
  2           33         39          33              34          31
  3           19         15          21              21          20
  4            6          1           6              10           3
  5            0          1           0               0           3
# Chi-squared test
chisq.test(survey_q3_contingency)
Warning: Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  survey_q3_contingency
X-squared = 22.933, df = 16, p-value = 0.1155

Plot prior expectation proportion bar plot across different groups

survey_q3_prop  <- as.data.frame(survey_q3_contingency)
# rename columns
names(survey_q3_prop) <- c("Q3.3", "Group", "Count")
# add a labelled column
survey_q3_prop <- survey_q3_prop %>%
  mutate(Q3.3_label = case_when(
    Q3.3 == "1" ~ "1-Strongly aligns",
    Q3.3 == "2" ~ "2-Somewhat aligns",
    Q3.3 == "3" ~ "3-Neutral",
    Q3.3 == "4" ~ "4-Somewhat does not align",
    Q3.3 == "5" ~ "5-Does not align at all",
  ))
# calculate proportions within each group
survey_q3_prop <- survey_q3_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q3_prop, aes(x = as.factor(`Q3.3_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q3.3 Prior Expectation Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

survey_q3_summary <- survey_q3_prop %>%
  group_by(`Q3.3_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `Q3.3_graph_label` = paste0(`Q3.3_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(survey_q3_summary, aes(x = "",y = proportion, fill = `Q3.3_graph_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Q3.3 Prior Expectation Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

Qxx.4 Confliction with Prior Expectation

How does the inflation forecast conflict with your expectations?
Variable: categorical
Method: calculate total number of people who think the forecast is not aligned with their expectation
Result: Among people who think the forecast is not aligned with their expectation, 90% percent of respondents thinks the forecast is lower than what they expected.

# Check the number of people answered this question
n_not_align <- sum(survey_q3_summary$total_count[4:5])
# Combine data from different groups
survey_q4 <- data.frame()
survey_q4_list <- list("Q4.4","Q6.4", "Q8.4", "Q10.4", "Q12.4")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q4_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q4_value", "group")
  survey_q4 <- rbind(survey_q4, temp_table)
}
survey_q4 <- survey_q4[!is.na(survey_q4$q4_value), ]
survey_q4_contingency <- table(survey_q4$q4_value, survey_q4$group)
# print the contingency table
print(survey_q4_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            1          0           2               0           0
  2            5          2           4              10           6

Plot confliction with prior expectation proportion bar plot across different groups

survey_q4_prop  <- as.data.frame(survey_q4_contingency)
# rename columns
names(survey_q4_prop) <- c("Q4.4", "Group", "Count")
# add a labelled column
survey_q4_prop <- survey_q4_prop %>%
  mutate(Q4.4_label = case_when(
    Q4.4 == "1" ~ "1-Higher than what I expected",
    Q4.4 == "2" ~ "2-Lower than what I expected"
  ))
# calculate proportions within each group
survey_q4_prop <- survey_q4_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q4_prop, aes(x = as.factor(`Q4.4_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  labs(
    title = "Q4.4 Confliction with Prior Expectation Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

Qxx.6 Probability of exactly 2.6%

what do you think is the probability of inflation being exactly 2.6%?
Definitive Correct Answer
descending order
Variable: categorical
Method: contingency table & proportion test
Result: There is no statistical difference in terms of correctly answering the probability of inflation being exactly 2.6%.

# combine data from different groups
survey_q6 <- data.frame()
survey_q6_list <- list("Q4.6","Q6.6", "Q8.6", "Q10.6", "Q12.6")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q6_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q6_value", "group")
  survey_q6 <- rbind(survey_q6, temp_table)
}
survey_q6$q6_value <- as.numeric(survey_q6$q6_value)

survey_q6_contingency <- table(survey_q6$q6_value, survey_q6$group)
print(survey_q6_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            0          0           1               0           0
  2            4          5          10               8           5
  3           18         12           3               6           5
  4            5          4           3               3           2
  5           20          5          20              22          25
  6            7         17          10              13          12
  7            8         16          14              14          12
# whether one proportion differs across groups
less_than_1_per <- survey_q6_contingency[7,]
survey_q6_group_total <- colSums(survey_q6_contingency)
prop.test(less_than_1_per, survey_q6_group_total)

    5-sample test for equality of proportions without continuity
    correction

data:  less_than_1_per out of survey_q6_group_total
X-squared = 4.0132, df = 4, p-value = 0.4042
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4    prop 5 
0.1290323 0.2711864 0.2295082 0.2121212 0.1967213 

Plot probability of exactly 2.6% proportion bar plot across different groups

survey_q6_prop  <- as.data.frame(survey_q6_contingency)
# rename columns
names(survey_q6_prop) <- c("Qxx.6", "Group", "Count")
# add a labelled column
survey_q6_prop <- survey_q6_prop %>%
  mutate(Qxx.6_label = case_when(
    Qxx.6 == "1" ~ "1->99%",
    Qxx.6 == "2" ~ "2-around 80%",
    Qxx.6 == "3" ~ "3-around 60%",
    Qxx.6 == "4" ~ "4-around 50%",
    Qxx.6 == "5" ~ "5-around 30%",
    Qxx.6 == "6" ~ "6-around 20%",
    Qxx.6 == "7" ~ "7-<1%"
  ))
# calculate proportions within each group
survey_q6_prop <- survey_q6_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q6_prop, aes(x = as.factor(`Qxx.6_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.6 Probability of exactly 2.6% Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_q6, aes(x = q6_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  labs(title = "Qxx.6 Probability of exactly 2.6% Histogram",
       x = "Response",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_q6$q6_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

Plot pie chart including all participants

survey_q6_summary <- survey_q6_prop %>%
  group_by(`Q6.6_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `Q6.6_graph_label` = paste0(`Q6.6_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(survey_q6_summary, aes(x = "",y = proportion, fill = `Q6.6_graph_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Qxx.6 Probability of exactly 2.6% Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

! Qxx.7 Probability of between 1.9% and 3.3%

what do you think is the probability of inflation being between 1.9% and 3.3%?
Definitive Correct Answer
descending order
Method: contingency table & proportion test
Result: There is statistical difference in control group in terms of the proportion of the correct answer of how people think the probability of inflation being between 1.9% and 3.3% is.

# combine data from different groups
survey_q7 <- data.frame()
survey_q7_list <- list("Q4.7","Q6.7", "Q8.7", "Q10.7", "Q12.7")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q7_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q7_value", "group")
  survey_q7 <- rbind(survey_q7, temp_table)
}
survey_q7$q7_value <- as.numeric(survey_q7$q7_value)

Test the proportion of correct answer

survey_q7_contingency <- table(survey_q7$q7_value, survey_q7$group)
# print the contingency table
print(survey_q7_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1           10          0           0               3           1
  2           23          7          11               9           9
  3           17         18          11              14           7
  4            9         13           7               8          10
  5            3         18          27              25          29
  6            0          3           5               7           4
  7            0          0           0               0           1
# correct answer
survey_q7_correct <- survey_q7_contingency[5,]
survey_q7_group_total <- colSums(survey_q7_contingency)
prop.test(survey_q7_correct, survey_q7_group_total)

    5-sample test for equality of proportions without continuity correction

data:  survey_q7_correct out of survey_q7_group_total
X-squared = 32.443, df = 4, p-value = 1.553e-06
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4    prop 5 
0.0483871 0.3050847 0.4426230 0.3787879 0.4754098 
# pairwise proportion test
pairwise.prop.test(
  x = survey_q7_contingency[5, ],
  n = colSums(survey_q7_contingency),
  p.adjust.method = "bonferroni" # or "holm", "BH"
)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  survey_q7_contingency[5, ] out of colSums(survey_q7_contingency) 

                0-controlled 1-errorbar 2-shadedbar 3-fanchartslice
1-errorbar      0.00489      -          -           -              
2-shadedbar     1.1e-05      1.00000    -           -              
3-fanchartslice 0.00017      1.00000    1.00000     -              
4-bellcurve     2.1e-06      0.84724    1.00000     1.00000        

P value adjustment method: bonferroni 

Plot probability of between 1.9% and 3.3% proportion bar plot across different groups

survey_q7_prop  <- as.data.frame(survey_q7_contingency)
# rename columns
names(survey_q7_prop) <- c("Qxx.7", "Group", "Count")
# add a labelled column
survey_q7_prop <- survey_q7_prop %>%
  mutate(Qxx.7_label = case_when(
    Qxx.7 == "1" ~ "1->99%",
    Qxx.7 == "2" ~ "2-around 80%",
    Qxx.7 == "3" ~ "3-around 60%",
    Qxx.7 == "4" ~ "4-around 50%",
    Qxx.7 == "5" ~ "5-around 30%",
    Qxx.7 == "6" ~ "6-around 20%",
    Qxx.7 == "7" ~ "7-<1%"
  ))
# calculate proportions within each group
survey_q7_prop <- survey_q7_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q7_prop, aes(x = as.factor(`Qxx.7_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.7 Probability of between 1.9% and 3.3% Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_q7, aes(x = q7_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.7 Probability of between 1.9% and 3.3% Histogram",
       x = "Qxx.7",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_q7$q7_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

Qxx.8 Probability of between 3.3% and 5.6%

what do you think is the probability of inflation being between 3.3% and 5.6%?
Definitive Correct Answer
descending order
Method: contingency table & proportion test
Result: The control group and the error bar group has shown statistical difference.

# combine data from different groups
survey_q8 <- data.frame()
survey_q8_list <- list("Q4.8","Q6.8", "Q8.8", "Q10.8", "Q12.8")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q8_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q8_value", "group")
  survey_q8 <- rbind(survey_q8, temp_table)
}
survey_q8$q8_value <- as.numeric(survey_q8$q8_value)

contingency table

survey_q8_contingency <- table(survey_q8$q8_value, survey_q8$group)
# print the contingency table
print(survey_q8_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            1          0           1               1           1
  2            3          2           3               2           7
  3           13          4           5              10           5
  4            5          5           9               6           2
  5           14         34          29              23          28
  6           18         13          11              22          12
  7            8          1           3               2           6
# correct answer
survey_q8_correct <- survey_q8_contingency[5,]
survey_q8_group_total <- colSums(survey_q8_contingency)
prop.test(survey_q8_correct, survey_q8_group_total)

    5-sample test for equality of proportions without continuity correction

data:  survey_q8_correct out of survey_q8_group_total
X-squared = 18.077, df = 4, p-value = 0.001192
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4    prop 5 
0.2258065 0.5762712 0.4754098 0.3484848 0.4590164 
# pairwise proportion test
pairwise.prop.test(
  x = survey_q8_contingency[5, ],
  n = colSums(survey_q8_contingency),
  p.adjust.method = "bonferroni" # or "holm", "BH"
)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  survey_q8_contingency[5, ] out of colSums(survey_q8_contingency) 

                0-controlled 1-errorbar 2-shadedbar 3-fanchartslice
1-errorbar      0.0017       -          -           -              
2-shadedbar     0.0666       1.0000     -           -              
3-fanchartslice 1.0000       0.1766     1.0000      -              
4-bellcurve     0.1118       1.0000     1.0000      1.0000         

P value adjustment method: bonferroni 

Plot probability of between 3.3% and 5.6% proportion bar plot across different groups

survey_q8_prop  <- as.data.frame(survey_q8_contingency)
# rename columns
names(survey_q8_prop) <- c("Qxx.8", "Group", "Count")
# add a labelled column
survey_q8_prop <- survey_q8_prop %>%
  mutate(Qxx.8_label = case_when(
    Qxx.8 == "1" ~ "1->99%",
    Qxx.8 == "2" ~ "2-around 80%",
    Qxx.8 == "3" ~ "3-around 60%",
    Qxx.8 == "4" ~ "4-around 50%",
    Qxx.8 == "5" ~ "5-around 30%",
    Qxx.8 == "6" ~ "6-around 20%",
    Qxx.8 == "7" ~ "7-<1%"
  ))
# calculate proportions within each group
survey_q8_prop <- survey_q8_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q8_prop, aes(x = as.factor(`Qxx.8_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.8 Probability of between 3.3% and 5.6% Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_q8, aes(x = q8_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.8 Probability of between 3.3% and 5.6% Histogram",
       x = "Qxx.8",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_q8$q8_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

! Qxx.10 Probability of ending outside the range

Based on the inflation forecast provided, what do you think is the probability of inflation ending up outside of the range from -0.4% to 5.6%?
Definitive Correct Answer (varied between group)
descending order
Variable: categorical
Method: calculate the proportion for each group + proportion test
Result: Control group perform significant worse than other groups.

# pairwise proportion test
pairwise.prop.test(
  x = setNames(survey_q10$correct, survey_q10$group),
  n = setNames(survey_q10$total,   survey_q10$group),
  p.adjust.method = "bonferroni" # or "holm", "BH"
)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  setNames(survey_q10$correct, survey_q10$group) out of setNames(survey_q10$total, survey_q10$group) 

              controlled errorbar shadedbar fanchartslice
errorbar      5.3e-05    -        -         -            
shadedbar     0.0135     1.0000   -         -            
fanchartslice 0.0039     1.0000   1.0000    -            
bellcurve     2.6e-07    1.0000   0.1781    0.3392       

P value adjustment method: bonferroni 

ggplot(survey_q10, aes(x = group, y = prop)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  geom_text(aes(label = scales::percent(prop, accuracy = 1)), vjust = -0.5) +
  labs(title = "Qxx.10 Probability of ending outside the range correct answer rate",
       x = "Group",
       y = "Proportion") +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()

Plot distribution for each individual group

ggplot(controlled_group, aes(x = as.numeric(as.character(Q4.10)))) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  scale_y_continuous(
    limits = c(0, 50),        # force y from 0 up to 60
    breaks = seq(0, 50, by=10) # ticks at 0, 10, 20, …, 60
  ) +
  geom_text(aes(label = ..count..), stat = "count", vjust = -0.5) +
  labs(
    title = "Controlled Group: Distribution of Q4.10 Responses",
    x     = "Q4.10 (numeric)",
    y     = "Count"
  ) +
  theme_minimal()

Qxx.11 Probability of higher than 6%

Based on the inflation forecast provided, what do you think is the probability of inflation ending up higher than 6%?
Definitive Correct Answer - 3
variable: categorical
Method: contingency table & proportion test
Result: The bell curve and the control group has shown significant difference. The majority people think the probability is extremely low (less than 1%).

Test the proportion of correct answer

survey_q11_contingency <- table(survey_q11$q11_value, survey_q11$group)
# print the contingency table
print(survey_q11_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            1          4           1               0           4
  2           13         12           9              10           9
  3           13         21          24              24          29
  4           33         15          24              30          16
  5            2          7           3               2           3
survey_q11_correct <- survey_q11_contingency[3,]
survey_q11_group_total <- colSums(survey_q11_contingency)
prop.test(survey_q11_correct, survey_q11_group_total)

    5-sample test for equality of proportions without continuity
    correction

data:  survey_q11_correct out of survey_q11_group_total
X-squared = 9.9199, df = 4, p-value = 0.0418
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4    prop 5 
0.2096774 0.3559322 0.3934426 0.3636364 0.4754098 

Post-hoc test

pairwise.prop.test(
  x = survey_q11_contingency[3, ],
  n = colSums(survey_q11_contingency),
  p.adjust.method = "bonferroni" # or "holm", "BH"
)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  survey_q11_contingency[3, ] out of colSums(survey_q11_contingency) 

                0-controlled 1-errorbar 2-shadedbar 3-fanchartslice
1-errorbar      1.000        -          -           -              
2-shadedbar     0.428        1.000      -           -              
3-fanchartslice 0.845        1.000      1.000       -              
4-bellcurve     0.035        1.000      1.000       1.000          

P value adjustment method: bonferroni 

Plot probability of higher than 6% proportion bar plot across different groups

survey_q11_prop  <- as.data.frame(survey_q11_contingency)
# rename columns
names(survey_q11_prop) <- c("Qxx.11", "Group", "Count")
# add a labelled column
survey_q11_prop <- survey_q11_prop %>%
  mutate(Qxx.11_label = case_when(
    Qxx.11 == "1" ~ "1-More than 20%",
    Qxx.11 == "2" ~ "3-5-10%",
    Qxx.11 == "3" ~ "4-1-5%",
    Qxx.11 == "4" ~ "5-Less than 1%",
    Qxx.11 == "5" ~ "2-10-20%"
  ))
# calculate proportions within each group
survey_q11_prop <- survey_q11_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q11_prop, aes(x = as.factor(`Qxx.11_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.11 Probability of higher than 6% Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

Qxx.12 Probability of higher than 3%

Based on the inflation forecast provided, what do you think is the probability of inflation ending up higher than 3%?
Definitive Correct Answer - 1
variable: categorical
Method: contingency table & proportion test
Result: There is no statistical difference and the majority people didn’t get the answer right.

# combine data from different groups
survey_q12 <- data.frame()
survey_q12_list <- list("Q4.12","Q6.12", "Q8.12", "Q10.12", "Q12.12")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q12_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q12_value", "group")
  survey_q12 <- rbind(survey_q12, temp_table)
}
survey_q12$q12_value <- as.numeric(survey_q12$q12_value)

Test the proportion of correct answer

survey_q12_contingency <- table(survey_q12$q12_value, survey_q12$group)
# print the contingency table
print(survey_q12_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            3          3           2               5           4
  2           15         14          19              12          13
  3           19         18          26              29          22
  4           11          7          11              12          13
  5           14         17           3               8           9
survey_q12_correct <- survey_q12_contingency[2,]
survey_q12_group_total <- colSums(survey_q12_contingency)
prop.test(survey_q12_correct, survey_q12_group_total)

    5-sample test for equality of proportions without continuity
    correction

data:  survey_q12_correct out of survey_q12_group_total
X-squared = 3.1893, df = 4, p-value = 0.5267
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4    prop 5 
0.2419355 0.2372881 0.3114754 0.1818182 0.2131148 

Plot probability of higher than 3% proportion bar plot across different groups

survey_q12_prop  <- as.data.frame(survey_q12_contingency)
# rename columns
names(survey_q12_prop) <- c("Qxx.12", "Group", "Count")
# add a labelled column
survey_q12_prop <- survey_q12_prop %>%
  mutate(Qxx.12_label = case_when(
    Qxx.12 == "1" ~ "1-More than 60%",
    Qxx.12 == "2" ~ "3-40-50%",
    Qxx.12 == "3" ~ "4-30-40%",
    Qxx.12 == "4" ~ "5-Less than 30%",
    Qxx.12 == "5" ~ "2-50-60%"
  ))
# calculate proportions within each group
survey_q12_prop <- survey_q12_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q12_prop, aes(x = as.factor(`Qxx.12_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.12 Probability of higher than 3% Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# force order for graph
survey_q12 <- survey_q12 %>%
  mutate(
    q12_value_re = factor(
      q12_value,
      levels = c(1, 5, 2, 3, 4)
    )
  )
# histogram including all participants
ggplot(survey_q12, aes(x = q12_value_re)) +
  geom_bar(fill = "steelblue", color = "white") +
  labs(
    title = "Qxx.12 Responses (forced 1-5-2-3-4 order)",
    x     = "Qxx.12",
    y     = "Count"
  ) +
  theme_minimal()

! Qxx.14 Probability of higher than 2% target

To keep inflation low and stable, Government sets an inflation target of 2%. Based on the inflation forecast provided, what do you think is the probability of inflation exceeding 2%?
Definitive Correct Answer - 3
variable: categorical
Method: contingency table & proportion test
Result: Control group is significant different from error Bar group and bell curve group; Error bar group has shown statistical difference compared to fan chart slice. 44% of total respondents can understand the probability of inflation being higher than 6% correctly.

# combine data from different groups
survey_q14 <- data.frame()
survey_q14_list <- list("Q4.14","Q6.14", "Q8.14", "Q10.14", "Q12.14")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q14_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q14_value", "group")
  survey_q14 <- rbind(survey_q14, temp_table)
}
survey_q14$q14_value <- as.numeric(survey_q14$q14_value)

Test the proportion of correct answer

survey_q14_correct <- survey_q14_contingency[3,]
survey_q14_group_total <- colSums(survey_q14_contingency)
prop.test(survey_q14_correct, survey_q14_group_total)

    5-sample test for equality of proportions without continuity
    correction

data:  survey_q14_correct out of survey_q14_group_total
X-squared = 21.144, df = 4, p-value = 0.0002965
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4    prop 5 
0.2580645 0.6101695 0.4754098 0.3333333 0.5409836 

Pairwise proportion test

pairwise.prop.test(
  x = survey_q14_contingency[3, ],
  n = colSums(survey_q14_contingency),
  p.adjust.method = "holm" # or "holm", "BH"
)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  survey_q14_contingency[3, ] out of colSums(survey_q14_contingency) 

                0-controlled 1-errorbar 2-shadedbar 3-fanchartslice
1-errorbar      0.0019       -          -           -              
2-shadedbar     0.1443       0.7772     -           -              
3-fanchartslice 1.0000       0.0281     0.7344      -              
4-bellcurve     0.0227       1.0000     1.0000      0.1754         

P value adjustment method: holm 

Plot probability of higher than 2% target proportion bar plot across different groups

survey_q14_prop  <- as.data.frame(survey_q14_contingency)
# rename columns
names(survey_q14_prop) <- c("Qxx.14", "Group", "Count")
# add a labelled column
survey_q14_prop <- survey_q14_prop %>%
  mutate(Qxx.14_label = case_when(
    Qxx.14 == "1" ~ "1->99%",
    Qxx.14 == "2" ~ "2-around 80%",
    Qxx.14 == "3" ~ "3-around 60%",
    Qxx.14 == "4" ~ "4-around 50%",
    Qxx.14 == "5" ~ "5-around 30%",
    Qxx.14 == "6" ~ "6-around 20%",
    Qxx.14 == "7" ~ "7-<1%"
  ))
# calculate proportions within each group
survey_q14_prop <- survey_q14_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q14_prop, aes(x = as.factor(`Qxx.14_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.14 Probability of higher than 2% target Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_q14, aes(x = q14_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.14 Probability of higher than 2% target Histogram",
       x = "Qxx.14",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_q14$q14_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

Qxx.15 Deviation from central estimate

Based on the inflation forecast provided, do you think there is a higher risk of inflation in 2026Q2 exceeding the central estimate or of being less than this central estimate?
Definitive Correct Answer - 3
variable: categorical
Method: contingency table & proportion test
Result: The control group shows significant difference compared to the shaded bar group in terms of the correctly choosing understanding the risk is equal. Among all participants, only around 8% respondents think there is downside risk. The largest proportion (48%) of participants believe there is upside risk.

# combine data from different groups
survey_q15 <- data.frame()
survey_q15_list <- list("Q4.15","Q6.15", "Q8.15", "Q10.15", "Q12.15")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q15_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q15_value", "group")
  survey_q15 <- rbind(survey_q15, temp_table)
}
survey_q15$q15_value <- as.numeric(survey_q15$q15_value)

Contingency table

survey_q15_correct <- survey_q15_contingency[3,]
survey_q15_group_total <- colSums(survey_q15_contingency)
prop.test(survey_q15_correct, survey_q15_group_total)

    5-sample test for equality of proportions without continuity
    correction

data:  survey_q15_correct out of survey_q15_group_total
X-squared = 14.519, df = 4, p-value = 0.005811
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4    prop 5 
0.2741935 0.4576271 0.5901639 0.5000000 0.3770492 

Pairwise proportion test

pairwise.prop.test(
  x = survey_q15_contingency[3, ],
  n = colSums(survey_q15_contingency),
  p.adjust.method = "bonferroni" # or "holm", "BH"
)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  survey_q15_contingency[3, ] out of colSums(survey_q15_contingency) 

                0-controlled 1-errorbar 2-shadedbar 3-fanchartslice
1-errorbar      0.5644       -          -           -              
2-shadedbar     0.0079       1.0000     -           -              
3-fanchartslice 0.1487       1.0000     1.0000      -              
4-bellcurve     1.0000       1.0000     0.2970      1.0000         

P value adjustment method: bonferroni 

Plot proportion bar plot across different groups

survey_q15_prop  <- as.data.frame(survey_q15_contingency)
# rename columns
names(survey_q15_prop) <- c("Qxx.15", "Group", "Count")
# add a labelled column
survey_q15_prop <- survey_q15_prop %>%
  mutate(Qxx.15_label = case_when(
    Qxx.15 == "1" ~ "1-bigger upside risk",
    Qxx.15 == "2" ~ "2-bigger downside risk",
    Qxx.15 == "3" ~ "3-equal risks on both sides"
  ))
# calculate proportions within each group
survey_q15_prop <- survey_q15_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q15_prop, aes(x = as.factor(`Qxx.15_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.15 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

Qxx.17 Self-reported likelihood of exactly 2.6%

How likely do you think it is that the inflation will be exactly 2.6%?
ascending value-increasing likelihood
Variable: treat as continuous
Method: Kruskal-Wallis test
Result: Fail to reject the null hypothesis. The overall distribution is skewed towards unlikely.

# combine data from different groups
survey_q17 <- data.frame()
survey_q17_list <- list("Q4.17_1","Q6.17_1", "Q8.17_1", "Q10.17_1", "Q12.17_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q17_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q17_value", "group")
  survey_q17 <- rbind(survey_q17, temp_table)
}
survey_q17$q17_value <- as.numeric(survey_q17$q17_value)

KW test

# check normality --> the data is not normally distributed
# shapiro.test(survey_q17$q17_value)

# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q17_value ~ group, data = survey_q17)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  q17_value by group
Kruskal-Wallis chi-squared = 1.4881, df = 4, p-value = 0.8287

Plot the distribution of different groups

# add labels
likelihood_labels = c(
    "9" = "Exceptionally unlikely",
    "10" = "Very unlikely",
    "11" = "Quite unlikely",
    "12" = "Fifty-fifty",
    "13" = "Quite likely",
    "14" = "Very likely",
    "15" = "Virtually certain"
  )
# histogram including all participants
ggplot(survey_q17, aes(x = q17_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.17 Self-reported likelihood of exactly 2.6% distribution",
       x = "Qxx.17",
       y = "Count") +
  scale_x_continuous(breaks = as.numeric(names(likelihood_labels)), 
                     labels = likelihood_labels) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


# Grouped bar-style histogram
ggplot(survey_q17, aes(x = factor(q17_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  # add labels
  scale_x_discrete(labels=likelihood_labels) +
  labs(
    title = "Qxx.17 Self-reported likelihood of exactly 2.6% distribution by group",
    x = "Qxx.17 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Qxx.21 Self-reported likelihood of inflation being between 1.9% and 3.3%

How likely do you think it is that the inflation will be between 1.9% and 3.3%?
ascending value-increasing likelihood
Variable: treat as continuous
Method: Kruskal-Wallis test
Result: Fail to reject the null hypothesis. The majority of respondents think it’s quite likely.

# combine data from different groups
survey_q21 <- data.frame()
survey_q21_list <- list("Q4.21_1","Q6.21_1", "Q8.21_1", "Q10.21_1", "Q12.21_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q21_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q21_value", "group")
  survey_q21 <- rbind(survey_q21, temp_table)
}
survey_q21$q21_value <- as.numeric(survey_q21$q21_value)

KW test

# check normality --> the data is not normally distributed
# shapiro.test(survey_q21$q21_value)

# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q21_value ~ group, data = survey_q21)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  q21_value by group
Kruskal-Wallis chi-squared = 8.6617, df = 4, p-value = 0.07013

Plot the distribution of different groups

# add labels
likelihood_labels = c(
    "9" = "Exceptionally unlikely",
    "10" = "Very unlikely",
    "11" = "Quite unlikely",
    "12" = "Fifty-fifty",
    "13" = "Quite likely",
    "14" = "Very likely",
    "15" = "Virtually certain"
  )

# Grouped bar-style histogram
ggplot(survey_q21, aes(x = factor(q21_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  # add labels
  scale_x_discrete(labels=likelihood_labels) +
  labs(
    title = "Qxx.21 Self-reported likelihood of inflation being between 1.9% and 3.3% distribution by group",
    x = "Qxx.21 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot bar chart including all participants

! Qxx.22 Self-reported likelihood of inflation being between 3.3% and 5.6%

How likely do you think it is that the inflation will be between 3.3% and 5.6%?
ascending value-increasing likelihood
Variable: treat as continuous
Method: Kruskal-Wallis test
Result: The distribution of shaded bar group and bell curve show statistical difference. Near half of the respondents think it’s quite unlikely.

# combine data from different groups
survey_q22 <- data.frame()
survey_q22_list <- list("Q4.22_1","Q6.22_1", "Q8.22_1", "Q10.22_1", "Q12.22_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q22_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q22_value", "group")
  survey_q22 <- rbind(survey_q22, temp_table)
}
survey_q22$q22_value <- as.numeric(survey_q22$q22_value)

KW test

dunnTest(q22_value ~ group, data = survey_q22, method = "bonferroni")
Warning: group was coerced to a factor.Dunn (1964) Kruskal-Wallis multiple comparison
  p-values adjusted with the Bonferroni method.

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_q22, aes(x = factor(q22_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  facet_wrap(~ group) +
  # add labels
  scale_x_discrete(labels=likelihood_labels) +
  labs(
    title = "Qxx.22 Self-reported likelihood of inflation being between 3.3% and 5.6% distribution by group",
    x = "Qxx.22 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot bar chart including all participants

# histogram including all participants
ggplot(survey_q22, aes(x = q22_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.22 Self-reported likelihood of inflation being between 3.3% and 5.6% distribution",
       x = "Qxx.22",
       y = "Count") +
  scale_x_continuous(breaks = as.numeric(names(likelihood_labels)), 
                     labels = likelihood_labels) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Qxx.23 Self-reported likelihood of inflation being higher than 3%

How likely do you think it is that the inflation will be higher than 3%?
ascending value-increasing likelihood
Variable: treat as continuous
Method: Kruskal-Wallis test
Result: Fail to reject the null hypothesis. The majority of respondents think it’s quite unlikely, but there is no significant difference.

# combine data from different groups
survey_q23 <- data.frame()
survey_q23_list <- list("Q4.23_1","Q6.23_1", "Q8.23_1", "Q10.23_1", "Q12.23_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q23_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q23_value", "group")
  survey_q23 <- rbind(survey_q23, temp_table)
}
survey_q23$q23_value <- as.numeric(survey_q23$q23_value)

KW test

# check normality --> the data is not normally distributed
# shapiro.test(survey_q23$q23_value)

# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q23_value ~ group, data = survey_q23)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  q23_value by group
Kruskal-Wallis chi-squared = 3.1999, df = 4, p-value = 0.525

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_q23, aes(x = factor(q23_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  # add labels
  scale_x_discrete(labels=likelihood_labels) +
  labs(
    title = "Qxx.23 Self-reported likelihood of inflation being higher than 3% distribution by group",
    x = "Qxx.23 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot bar chart including all participants

# histogram including all participants
ggplot(survey_q23, aes(x = q23_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.23 Self-reported likelihood of inflation being higher than 3% distribution",
       x = "Qxx.23",
       y = "Count") +
  scale_x_continuous(breaks = as.numeric(names(likelihood_labels)), 
                     labels = likelihood_labels) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Qxx.26 Accuracy of central estimate

On a scale of 1 to 10, where 1 means not accurate at all and 10 means very accurate, how accurate do you think the central estimate in the graph is?
1-Not accurate at all; 10-Very accurate
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_q26 <- data.frame()
survey_q26_list <- list("Q4.26_1","Q6.26_1", "Q8.26_1", "Q10.26_1", "Q12.26_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q26_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q26_value", "group")
  survey_q26 <- rbind(survey_q26, temp_table)
}
survey_q26$q26_value <- as.numeric(survey_q26$q26_value)

Statistical test

# Initial Check
summary(survey_q26$q26_value)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   6.000   7.000   6.421   7.000  10.000 
# check normality --> the data is not normally distributed
# shapiro.test(survey_q26$q26_value)

# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q26_value ~ group, data = survey_q26)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  q26_value by group
Kruskal-Wallis chi-squared = 1.3483, df = 4, p-value = 0.8531

Summary statistics

# Summary statistics
survey_q26_summary <- survey_q26 %>%
  group_by(group) %>%
  summarise(
    mean = mean(q26_value, na.rm = TRUE),
    median = median(q26_value, na.rm = TRUE),
    sd = sd(q26_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram\
ggplot(survey_q26, aes(x = factor(q26_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  labs(
    title = "Qxx.26 Accuracy of central estimate distribution by group",
    x = "Qxx.26 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Qxx.27 Certainty of central estimate

On a scale of 1 to 10, where 1 means very uncertain and 10 means very certain, how certain or uncertain do you think the inflation forecast for 2026 Q2 is?
1-Very uncertain; 10-Very certain
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_q27 <- data.frame()
survey_q27_list <- list("Q4.27_1","Q6.27_1", "Q8.27_1", "Q10.27_1", "Q12.27_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q27_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q27_value", "group")
  survey_q27 <- rbind(survey_q27, temp_table)
}
survey_q27$q27_value <- as.numeric(survey_q27$q27_value)

Statistical test

# Initial Check
# summary(survey_q27$q27_value)
# check normality --> the data is not normally distributed
# shapiro.test(survey_q27$q27_value)
# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q27_value ~ group, data = survey_q27)
print(kruskal_test)

Summary statistics

# Summary statistics
survey_q27_summary <- survey_q27 %>%
  group_by(group) %>%
  summarise(
    mean = mean(q27_value, na.rm = TRUE),
    median = median(q27_value, na.rm = TRUE),
    sd = sd(q27_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_q27, aes(x = factor(q27_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  facet_wrap(~ group) +
  labs(
    title = "Qxx.27 The distribution of ceartainty/uncertainty of the central estimate by group",
    x = "Qxx.27 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

Qxx.29 Representativeness of the uncertainty

On a scale of 1 to 10, where 1 means not representative at all and 10 means very representative, how representative do you think the uncertainty being communicated is (i.e., how well the given information reflects the true variability or uncertainty of the forecast?)
1-Not representative at all; 10-Very representative
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_q29 <- data.frame()
survey_q29_list <- list("Q4.29_1","Q6.29_1", "Q8.29_1", "Q10.29_1", "Q12.29_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q29_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q29_value", "group")
  survey_q29 <- rbind(survey_q29, temp_table)
}
survey_q29$q29_value <- as.numeric(survey_q29$q29_value)

Statistical test

# Initial Check
# summary(survey_q29$q29_value)
# check normality --> the data is not normally distributed
# shapiro.test(survey_q29$q29_value)
# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q29_value ~ group, data = survey_q29)
print(kruskal_test)

Summary statistics

# Summary statistics
survey_q29_summary <- survey_q29 %>%
  group_by(group) %>%
  summarise(
    mean = mean(q29_value, na.rm = TRUE),
    median = median(q29_value, na.rm = TRUE),
    sd = sd(q29_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_q29, aes(x = factor(q29_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  labs(
    title = "Qxx.29 The distribution of representativeness of the uncertainty by group",
    x = "Qxx.29 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

! Qxx.30 Readability of the Forecast

On a scale of 1 to 10, where 1 means very difficult and 10 means very easy, how easy or difficult do you find the graph to understand?
1-Very difficult; 10-Very easy
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: Fail to reject the null hypothesis. There are statistical difference between control group vs. fan chart slice group; control group vs. bell curve; error bar group vs. bell curve group.

# combine data from different groups
survey_q30 <- data.frame()
survey_q30_list <- list("Q4.30_1","Q6.30_1", "Q8.30_1", "Q10.30_1", "Q12.30_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q30_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q30_value", "group")
  survey_q30 <- rbind(survey_q30, temp_table)
}
survey_q30$q30_value <- as.numeric(survey_q30$q30_value)

Statistical test

# Initial Check
# summary(survey_q30$q30_value)
# check normality --> the data is not normally distributed
# shapiro.test(survey_q30$q30_value)
# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q30_value ~ group, data = survey_q30)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  q30_value by group
Kruskal-Wallis chi-squared = 21.14, df = 4, p-value = 0.0002971
# Post-hoc test
dunnTest(q30_value ~ group, data = survey_q30, method = "bonferroni")
Warning: group was coerced to a factor.Dunn (1964) Kruskal-Wallis multiple comparison
  p-values adjusted with the Bonferroni method.

Summary statistics

# Summary statistics
survey_q30_summary <- survey_q30 %>%
  group_by(group) %>%
  summarise(
    mean = mean(q30_value, na.rm = TRUE),
    median = median(q30_value, na.rm = TRUE),
    sd = sd(q30_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_q30, aes(x = factor(q30_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  labs(
    title = "Qxx.30 The distribution of readability of the forecast by group",
    x = "Qxx.30 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

Qxx.31 Trust of the Forecast

On a scale of 1 to 10, where 1 means you don’t trust the inflation forecast at all and 10 means you fully trust it, how much do you trust the inflation forecast shown in the graph?
1-Don’t trust at all; 10-Fully trust
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_q31 <- data.frame()
survey_q31_list <- list("Q4.31_1","Q6.31_1", "Q8.31_1", "Q10.31_1", "Q12.31_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_q31_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q31_value", "group")
  survey_q31 <- rbind(survey_q31, temp_table)
}
survey_q31$q31_value <- as.numeric(survey_q31$q31_value)

Statistical test

kruskal_test <- kruskal.test(q31_value ~ group, data = survey_q31)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  q31_value by group
Kruskal-Wallis chi-squared = 3.7739, df = 4, p-value = 0.4375

Summary statistics

# Summary statistics
survey_q31_summary <- survey_q31 %>%
  group_by(group) %>%
  summarise(
    mean = mean(q31_value, na.rm = TRUE),
    median = median(q31_value, na.rm = TRUE),
    sd = sd(q31_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_q31, aes(x = factor(q31_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  labs(
    title = "Qxx.31 The distribution of trust of the forecast by group",
    x = "Qxx.31 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

Skewed Data

Qxx.33 Probability of higher than 3%

Based on the inflation forecast provided, what do you think is the probability of inflation ending up higher than 3%?
Definitive Correct Answer - 5
Variable: categorical
Method: contingency table & proportion test
Result: There is no statistical difference across different groups and the largest proportion of participants can understand the probability correctly, but only account for 28% of the entire respondents.

# combine data from different groups
survey_q33 <- data.frame()
survey_q33_list <- list("Q6.33","Q8.33", "Q10.33", "Q12.33")
for (i in seq_along(skewed_group_list)) {
  df <- skewed_group_list[[i]]
  col <- survey_q33_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q33_value", "group")
  survey_q33 <- rbind(survey_q33, temp_table)
}
survey_q33$q33_value <- as.numeric(survey_q33$q33_value)

Test the proportion of correct answer

survey_q33_contingency <- table(survey_q33$q33_value, survey_q33$group)
print(survey_q33_contingency)
   
    1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1         14          12              11           7
  2          8          12              10          16
  3          9          10              20          11
  4          4           5               6           5
  5         24          22              19          22
survey_q33_correct <- survey_q33_contingency[5,]
survey_q33_group_total <- colSums(survey_q33_contingency)
prop.test(survey_q33_correct, survey_q33_group_total)

    4-sample test for equality of proportions without continuity
    correction

data:  survey_q33_correct out of survey_q33_group_total
X-squared = 2.0053, df = 3, p-value = 0.5713
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4 
0.4067797 0.3606557 0.2878788 0.3606557 

Plot probability of higher than 3% (proportion bar plot across different groups)

survey_q33_prop  <- as.data.frame(survey_q33_contingency)
# rename columns
names(survey_q33_prop) <- c("Qxx.33", "Group", "Count")
# add a labelled column
survey_q33_prop <- survey_q33_prop %>%
  mutate(Qxx.33_label = case_when(
    Qxx.33 == "1" ~ "1-More than 60%",
    Qxx.33 == "2" ~ "3-40-50%",
    Qxx.33 == "3" ~ "4-30-40%",
    Qxx.33 == "4" ~ "5-Less than 30%",
    Qxx.33 == "5" ~ "2-50-60%"
  ))
# calculate proportions within each group
survey_q33_prop <- survey_q33_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q33_prop, aes(x = as.factor(`Qxx.33_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.33 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# force order for graph
survey_q33 <- survey_q33 %>%
  mutate(
    q33_value_re = factor(
      q33_value,
      levels = c(1, 5, 2, 3, 4)
    )
  )
# histogram including all participants
ggplot(survey_q33, aes(x = q33_value_re)) +
  geom_bar(fill = "steelblue", color = "white") +
  labs(
    title = "Qxx.33 Responses (forced 1-5-2-3-4 order)",
    x     = "Qxx.33",
    y     = "Count"
  ) +
  theme_minimal()

Qxx.34 Self-reported likelihood of inflation being higher than 3%

How likely do you think it is that the inflation will be higher than 3%?
ascending value-increasing likelihood
Variable: treat as continuous
Method: Kruskal-Wallis test
Result: Fail to reject the null hypothesis. The majority of respondents think it’s quite likely.

# combine data from different groups
survey_q34 <- data.frame()
survey_q34_list <- list("Q6.34_1","Q8.34_1", "Q10.34_1", "Q12.34_1")
for (i in seq_along(skewed_group_list)) {
  df <- skewed_group_list[[i]]
  col <- survey_q34_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q34_value", "group")
  survey_q34 <- rbind(survey_q34, temp_table)
}
survey_q34$q34_value <- as.numeric(survey_q34$q34_value)

KW test

# check normality --> the data is not normally distributed
# shapiro.test(survey_q34$q34_value)

# run Kruskal-Wallis test
kruskal_test <- kruskal.test(q34_value ~ group, data = survey_q34)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  q34_value by group
Kruskal-Wallis chi-squared = 5.5506, df = 3, p-value = 0.1356

Plot the distribution of different groups

Plot bar chart including all participants

# histogram including all participants
ggplot(survey_q34, aes(x = q34_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.34 Self-reported likelihood of inflation being higher than 3% distribution",
       x = "Qxx.34",
       y = "Count") +
  scale_x_continuous(breaks = as.numeric(names(likelihood_labels)), 
                     labels = likelihood_labels) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Qxx.36 Deviation from central estimate

Based on the inflation forecast provided, do you think there is a higher risk of inflation exceeding the central estimate or of being less than this central estimate?
Definitive Correct Answer - 1
Variable: categorical
Method: contingency table & proportion test
Result: There is no statistical difference across group. 68% of respondents can understand there is bigger upside risk.

# combine data from different groups
survey_q36 <- data.frame()
survey_q36_list <- list("Q6.36","Q8.36", "Q10.36", "Q12.36")
for (i in seq_along(skewed_group_list)) {
  df <- skewed_group_list[[i]]
  col <- survey_q36_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q36_value", "group")
  survey_q36 <- rbind(survey_q36, temp_table)
}
survey_q36$q36_value <- as.numeric(survey_q36$q36_value)

Contingency table

survey_q36_contingency <- table(survey_q36$q36_value, survey_q36$group)
print(survey_q36_contingency)
   
    1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1         38          42              47          41
  2          5           1               7           6
  3         16          18              12          14
chisq_result <- chisq.test(survey_q36_contingency)
Warning: Chi-squared approximation may be incorrect
print(chisq_result)

    Pearson's Chi-squared test

data:  survey_q36_contingency
X-squared = 6.2063, df = 6, p-value = 0.4005

Test the proportion of correct answer

survey_q36_correct <- survey_q36_contingency[1,]
survey_q36_group_total <- colSums(survey_q36_contingency)
prop.test(survey_q36_correct, survey_q36_group_total)

    4-sample test for equality of proportions without continuity
    correction

data:  survey_q36_correct out of survey_q36_group_total
X-squared = 0.70091, df = 3, p-value = 0.873
alternative hypothesis: two.sided
sample estimates:
   prop 1    prop 2    prop 3    prop 4 
0.6440678 0.6885246 0.7121212 0.6721311 

Plot proportion bar plot across different groups

survey_q36_prop  <- as.data.frame(survey_q36_contingency)
# rename columns
names(survey_q36_prop) <- c("Qxx.36", "Group", "Count")
# add a labelled column
survey_q36_prop <- survey_q36_prop %>%
  mutate(Qxx.36_label = case_when(
    Qxx.36 == "1" ~ "1-bigger upside risk",
    Qxx.36 == "2" ~ "2-bigger downside risk",
    Qxx.36 == "3" ~ "3-equal risks on both sides"
  ))
# calculate proportions within each group
survey_q36_prop <- survey_q36_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q36_prop, aes(x = as.factor(`Qxx.36_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.36 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_q36, aes(x = q36_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.36 Answer Bar Chart",
       x = "Qxx.36",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_q36$q36_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

? Qxx.37 Risk of ending outside

If the actual inflation ends up outside the black line, which side is more likely, based on the uncertainty depicted in the graph?
Definitive Correct Answer - 1
Variable: categorical
Method: contingency table & proportion test
Result: 63% respondents think if the actual inflation ends up outside, it’s more likely to be on the upper side.

# combine data from different groups
survey_q37 <- data.frame()
survey_q37_list <- list("Q6.37","Q8.37", "Q10.37", "Q12.37")
for (i in seq_along(skewed_group_list)) {
  df <- skewed_group_list[[i]]
  col <- survey_q37_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("q37_value", "group")
  survey_q37 <- rbind(survey_q37, temp_table)
}
survey_q37$q37_value <- as.numeric(survey_q37$q37_value)

Contingency table

# pairwise proportion test
pairwise.prop.test(
  x = survey_q37_contingency[1,],
  n = colSums(survey_q37_contingency),
  p.adjust.method = "bonferroni" # or "holm", "BH"
)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  survey_q37_contingency[1, ] out of colSums(survey_q37_contingency) 

                1-errorbar 2-shadedbar 3-fanchartslice
2-shadedbar     1.00       -           -              
3-fanchartslice 0.11       0.16        -              
4-bellcurve     1.00       1.00        0.40           

P value adjustment method: bonferroni 

Plot proportion bar plot across different groups

survey_q37_prop  <- as.data.frame(survey_q37_contingency)
# rename columns
names(survey_q37_prop) <- c("Qxx.37", "Group", "Count")
# add a labelled column
survey_q37_prop <- survey_q37_prop %>%
  mutate(Qxx.37_label = case_when(
    Qxx.37 == "1" ~ "1-More likely to be on the upper side",
    Qxx.37 == "2" ~ "2-More likely to be on the lower side",
    Qxx.37 == "3" ~ "3-Equal chances of being on either side"
  ))
# calculate proportions within each group
survey_q37_prop <- survey_q37_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_q37_prop, aes(x = as.factor(`Qxx.37_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "Qxx.37 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_q37, aes(x = q37_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "Qxx.37 Answer Bar Chart",
       x = "Qxx.37",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_q37$q37_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

Decision-making

D.3 Investment Decision

Which bond would you choose to invest in?
Variable: categorical
Method: contingency table & proportion test
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_d3 <- data.frame()
survey_d3_list <- list("Q5.3","Q7.3", "Q9.3", "Q11.3", "Q13.3")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_d3_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d3_value", "group")
  survey_d3 <- rbind(survey_d3, temp_table)
}
survey_d3$d3_value <- as.numeric(survey_d3$d3_value)

Contingency table

survey_d3_contingency <- table(survey_d3$d3_value, survey_d3$group)
print(survey_d3_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1           22         17          24              22          17
  2           40         42          37              44          44
# chi-squared test
chisq.test(survey_d3_contingency)

    Pearson's Chi-squared test

data:  survey_d3_contingency
X-squared = 2.4805, df = 4, p-value = 0.6481

Plot proportion bar plot across different groups

survey_d3_prop  <- as.data.frame(survey_d3_contingency)
# rename columns
names(survey_d3_prop) <- c("D.3", "Group", "Count")
# add a labelled column
survey_d3_prop <- survey_d3_prop %>%
  mutate(D.3_label = case_when(
    D.3 == "1" ~ "A. Nominal Bond",
    D.3 == "2" ~ "B. Inflation-Protected Bond"
  ))
# calculate proportions within each group
survey_d3_prop <- survey_d3_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_d3_prop, aes(x = as.factor(`D.3_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "D.3 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

survey_d3_summary <- survey_d3_prop %>%
  group_by(`D.3_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `D.3_graph_label` = paste0(`D.3_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(survey_d3_summary, aes(x = "",y = proportion, fill = `D.3_graph_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "D.3 Investment Decision Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

D.4 Confidence in decision-making

On a scale of 1 to 10, where 1 means not confident at all and 10 means very confident, how confident are you in making the decision?
1-Not confident at all; 10-Very confident
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_d4 <- data.frame()
survey_d4_list <- list("Q5.4_1","Q7.4_1", "Q9.4_1", "Q11.4_1", "Q13.4_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_d4_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d4_value", "group")
  survey_d4 <- rbind(survey_d4, temp_table)
}
survey_d4$d4_value <- as.numeric(survey_d4$d4_value)

Statistical test

# Initial Check
# summary(survey_d4$d4_value)
# check normality --> the data is not normally distributed
# shapiro.test(survey_d4$d4_value)

# run Kruskal-Wallis test
kruskal_test <- kruskal.test(d4_value ~ group, data = survey_d4)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  d4_value by group
Kruskal-Wallis chi-squared = 7.0487, df = 4, p-value = 0.1333

Summary statistics

# Summary statistics
survey_d4_summary <- survey_d4 %>%
  group_by(group) %>%
  summarise(
    mean = mean(d4_value, na.rm = TRUE),
    median = median(d4_value, na.rm = TRUE),
    sd = sd(d4_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_d4, aes(x = factor(d4_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  facet_wrap(~ group) +
  labs(
    title = "D.4 The distribution of confidence in decision-making by group",
    x = "D.4 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

D.6 Considering nominal bond

If the probability of inflation being low (≤ 3%) is greater than the following percentages, I would consider investing in the nominal bond:
Variable: categorical
Method: contingency table & chi-squared test
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_d6 <- data.frame()
survey_d6_list <- list("Q5.6","Q7.6", "Q9.6", "Q11.6", "Q13.6")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_d6_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d6_value", "group")
  survey_d6 <- rbind(survey_d6, temp_table)
}
survey_d6$d6_value <- as.numeric(survey_d6$d6_value)

Contingency table

survey_d6_contingency <- table(survey_d6$d6_value, survey_d6$group)
print(survey_d6_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            0          1           0               3           2
  2            2          4           1               4           3
  3            6          5           8               2           2
  4            2          5           5               6           9
  5           15         10           8              12          10
  7            6          8           7              14           8
  8            9          9           8               3          10
# run chi-squared test
chisq_result <- chisq.test(survey_d6_contingency)
Warning: Chi-squared approximation may be incorrect
print(chisq_result)

    Pearson's Chi-squared test

data:  survey_d6_contingency
X-squared = 28.8, df = 24, p-value = 0.2277

Plot proportion bar plot across different groups

survey_d6_prop  <- as.data.frame(survey_d6_contingency)
# rename columns
names(survey_d6_prop) <- c("D.6", "Group", "Count")
# add a labelled column
survey_d6_prop <- survey_d6_prop %>%
  mutate(D.6_label = case_when(
    D.6 == "1" ~ "1-40%",
    D.6 == "2" ~ "2-50%",
    D.6 == "3" ~ "3-60%",
    D.6 == "4" ~ "4-do not think about probability",
    D.6 == "5" ~ "5-choose an inflation-protected bond",
    D.6 == "7" ~ "6-70%",
    D.6 == "8" ~ "7-80%"
  ))
# calculate proportions within each group
survey_d6_prop <- survey_d6_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_d6_prop, aes(x = as.factor(`D.6_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "D.6 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_d6, aes(x = d6_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "D.6 Histogram",
       x = "D.6",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_d6$d6_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

D.7 Considering inflation-protected bond

If the probability of inflation being high (> 3%) is greater than the following percentages, I would consider investing in the inflation-protected bond:
Variable: categorical
Method: contingency table & chi-squared test
*Result: Fail to reject the null hypothesis.**

# combine data from different groups
survey_d7 <- data.frame()
survey_d7_list <- list("Q5.7","Q7.7", "Q9.7", "Q11.7", "Q13.7")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_d7_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d7_value", "group")
  survey_d7 <- rbind(survey_d7, temp_table)
}
survey_d7$d7_value <- as.numeric(survey_d7$d7_value)

Contingency table

survey_d7_contingency <- table(survey_d7$d7_value, survey_d7$group)
print(survey_d7_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1            2          0           5               1           0
  2            3          4           0               6           3
  3            2          4           6               5           5
  4            6          1           4               3           4
  5            1          3           1               4           3
  7            3          4           7               2           2
  8            5          1           1               1           0
# run chi-squared test
chisq_result <- chisq.test(survey_d7_contingency)
Warning: Chi-squared approximation may be incorrect
print(chisq_result)

    Pearson's Chi-squared test

data:  survey_d7_contingency
X-squared = 35.733, df = 24, p-value = 0.05824

Plot proportion bar plot across different groups

survey_d7_prop  <- as.data.frame(survey_d7_contingency)
# rename columns
names(survey_d7_prop) <- c("D.7", "Group", "Count")
# add a labelled column
survey_d7_prop <- survey_d7_prop %>%
  mutate(D.7_label = case_when(
    D.7 == "1" ~ "1-40%",
    D.7 == "2" ~ "2-50%",
    D.7 == "3" ~ "3-60%",
    D.7 == "4" ~ "4-do not think about probability",
    D.7 == "5" ~ "5-always choose a nominal bond",
    D.7 == "7" ~ "6-70%",
    D.7 == "8" ~ "7-80%"
  ))
# calculate proportions within each group
survey_d7_prop <- survey_d7_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_d7_prop, aes(x = as.factor(`D.7_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  facet_wrap(~Group)+
  labs(
    title = "D.7 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_d7, aes(x = d7_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "D.7 Histogram",
       x = "D.7",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_d7$d7_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

D.8 Impact on Desicion-making

Considering the payoff for the Nominal Bond, which of the following has a larger impact on your decision-making?
Variable: categorical
Method: contingency table & chi-squared test
Result: Fail to reject the null hypothesis.

# combine data from different groups
survey_d8 <- data.frame()
survey_d8_list <- list("Q5.8","Q7.8", "Q9.8", "Q11.8", "Q13.8")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_d8_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d8_value", "group")
  survey_d8 <- rbind(survey_d8, temp_table)
}
survey_d8$d8_value <- as.numeric(survey_d8$d8_value)

Contingency table

survey_d8_contingency <- table(survey_d8$d8_value, survey_d8$group)
print(survey_d8_contingency)
   
    0-controlled 1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1           33         28          35              43          40
  2           16         15          19              12          13
  3           13         16           7              11           8
# run chi-squared test
chisq_result <- chisq.test(survey_d8_contingency)
print(chisq_result)

    Pearson's Chi-squared test

data:  survey_d8_contingency
X-squared = 10.474, df = 8, p-value = 0.2333

Plot proportion bar plot across different groups

survey_d8_prop  <- as.data.frame(survey_d8_contingency)
# rename columns
names(survey_d8_prop) <- c("D.8", "Group", "Count")
# add a labelled column
survey_d8_prop <- survey_d8_prop %>%
  mutate(D.8_label = case_when(
    D.8 == "1" ~ "1-potential loss",
    D.8 == "2" ~ "2-potential gain",
    D.8 == "3" ~ "3-potential loss and gain have the same impact"
  ))
# calculate proportions within each group
survey_d8_prop <- survey_d8_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_d8_prop, aes(x = as.factor(`D.8_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "D.8 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot the histogram including all participants

# histogram including all participants
ggplot(survey_d8, aes(x = d8_value)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "white") +
  # facet_wrap(~ group) +
  labs(title = "D.8 Histogram",
       x = "D.8",
       y = "Count") +
  scale_x_continuous(breaks = seq(0, max(survey_d8$d8_value, na.rm = TRUE), by = 1)) +
  theme_minimal()

D.9 Effectiveness of the graph for decision-making

On a scale of 1 to 10, where 1 means the forecast was not effective at all and 10 means it was very effective, how effective do you think the forecast was in assisting your decision-making?
1-Not effective at all; 10-Very effective
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: At least one group is statistically significant than others.

# combine data from different groups
survey_d9 <- data.frame()
survey_d9_list <- list("Q5.9_1","Q7.9_1", "Q9.9_1", "Q11.9_1", "Q13.9_1")
for (i in seq_along(group_list)) {
  df <- group_list[[i]]
  col <- survey_d9_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d9_value", "group")
  survey_d9 <- rbind(survey_d9, temp_table)
}
survey_d9$d9_value <- as.numeric(survey_d9$d9_value)

Statistical test

# Initial Check
# summary(survey_d9$d9_value)
# check normality --> the data is not normally distributed
# shapiro.test(survey_d9$d9_value)

# run Kruskal-Wallis test
kruskal_test <- kruskal.test(d9_value ~ group, data = survey_d9)
print(kruskal_test)

    Kruskal-Wallis rank sum test

data:  d9_value by group
Kruskal-Wallis chi-squared = 10.047, df = 4, p-value = 0.03964
# Post-hoc test
dunnTest(d9_value ~ group, data = survey_d9, method = "bonferroni")
Warning: group was coerced to a factor.Dunn (1964) Kruskal-Wallis multiple comparison
  p-values adjusted with the Bonferroni method.

Summary statistics

# Summary statistics
survey_d9_summary <- survey_d9 %>%
  group_by(group) %>%
  summarise(
    mean = mean(d9_value, na.rm = TRUE),
    median = median(d9_value, na.rm = TRUE),
    sd = sd(d9_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_d9, aes(x = factor(d9_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  labs(
    title = "D.9 The distribution of effectiveness of the graph for decision-making by group",
    x = "D.9 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

? D.12 Skewed Investment Decision

Which bond would you choose to invest in?
Variable: categorical
Method: contingency table & chi-squared test
Result: There is significant difference in at least one group.

# combine data from different groups
survey_d12 <- data.frame()
survey_d12_list <- list("Q7.12", "Q9.12", "Q11.12", "Q13.12")
for (i in seq_along(skewed_group_list)) {
  df <- skewed_group_list[[i]]
  col <- survey_d12_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d12_value", "group")
  survey_d12 <- rbind(survey_d12, temp_table)
}
survey_d12$d12_value <- as.numeric(survey_d12$d12_value)

Contingency table

print(survey_d12_contingency)
   
    1-errorbar 2-shadedbar 3-fanchartslice 4-bellcurve
  1          8          21              25           8
  2         51          40              41          53

Plot proportion bar plot across different groups

survey_d12_prop  <- as.data.frame(survey_d12_contingency)
# rename columns
names(survey_d12_prop) <- c("D.12", "Group", "Count")
# add a labelled column
survey_d12_prop <- survey_d12_prop %>%
  mutate(D.12_label = case_when(
    D.12 == "1" ~ "A. Nominal Bond",
    D.12 == "2" ~ "B. Inflation-Protected Bond"
  ))
# calculate proportions within each group
survey_d12_prop <- survey_d12_prop %>%
  group_by(Group) %>%
  mutate(Proportion = Count / sum(Count))
ggplot(survey_d12_prop, aes(x = as.factor(`D.12_label`), y = Proportion, fill = Group)) + geom_col(position = "dodge") +
  # facet_wrap(~Group)+
  labs(
    title = "D.12 Answer Propotion Plot across Groups",
    x = "Response",
    y = "Proportion"
  ) +
   scale_fill_brewer(palette = "Set2")+
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Plot pie chart including all participants

survey_d12_summary <- survey_d12_prop %>%
  group_by(`D.12_label`) %>%
  summarise(total_count = sum(Count), .groups = "drop") %>%
  mutate(proportion = total_count / sum(total_count),
         `D.12_graph_label` = paste0(`D.12_label`, " (", round(proportion * 100, 2), " %)"))
ggplot(survey_d12_summary, aes(x = "",y = proportion, fill = `D.12_graph_label`)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "D.12 Investment Decision Summary Pie Chart",
       x = "",
       y = "") +
  theme_minimal() +
  theme(axis.text.x = element_blank())

D.13 Skewed Confidentce in decision-making

On a scale of 1 to 10, where 1 means not confident at all and 10 means very confident, how confident are you in making the decision?
1-Not confident at all; 10-Very confident
Variable: continuous
Method: ANNOVA test or KW test (depends on whether it’s normally distributed)
Result: At least one group is statistically significant than others.

# combine data from different groups
survey_d13 <- data.frame()
survey_d13_list <- list("Q7.13_1", "Q9.13_1", "Q11.13_1", "Q13.13_1")
for (i in seq_along(skewed_group_list)) {
  df <- skewed_group_list[[i]]
  col <- survey_d13_list[[i]]
  temp_table <- df[, c(col, "group")]
  names(temp_table) <- c("d13_value", "group")
  survey_d13 <- rbind(survey_d13, temp_table)
}
survey_d13$d13_value <- as.numeric(survey_d13$d13_value)

Statistical test

anova_test <- aov(d13_value ~ group, data = survey_d13)
summary(anova_test)
             Df Sum Sq Mean Sq F value Pr(>F)
group         3   14.2   4.721   1.181  0.317
Residuals   243  971.1   3.996               

Summary statistics

# Summary statistics
survey_d13_summary <- survey_d13 %>%
  group_by(group) %>%
  summarise(
    mean = mean(d13_value, na.rm = TRUE),
    median = median(d13_value, na.rm = TRUE),
    sd = sd(d13_value, na.rm = TRUE)
  )

Plot the distribution of different groups

# Grouped bar-style histogram
ggplot(survey_d13, aes(x = factor(d13_value), fill = factor(group))) +
  geom_bar(position = "dodge") +
  # facet_wrap(~ group) +
  labs(
    title = "D.13 The distribution of confidence in decision-making by group",
    x = "D.13 Response",
    y = "Count",
    fill = "Group"
  ) +
  theme_minimal()

Cross-tabulation

Current Inflation Knowledge vs. Inflation Forecast Knowledge

Skewed Data vs. Unskewed Data ( understanding and decision making)

For people who can correctly understand the probability (? which), what decision do they make? –> I am thinking propotion test see reduced probability.

Does familarity with the graph type affect understanding and the decision?

Statistical Testing

Basics

Type I error- false positives (saying there’s a difference when there isn’t) ## Chi-squared test ### Post-hoc test 1. Standardized residuals

chisq_result <- chisq.test(q3_4_contingency)
std_resid <- chisq_result$stdres
print(std_resid)

Cells with absolute value > ~2 (or > 1.96 for 95% confidence)indicate contributing most to the overall chi-squared

  1. Pairwise proportion tests: can only compare one value
pairwise.prop.test(
  x = q3_4_contingency[, 1:ncol(q3_4_contingency)],  # counts per group
  n = colSums(q3_4_contingency),                     # total per group
  p.adjust.method = "bonferroni"                     # or "holm", "BH"
)

ANOVA test

ANOVA only compares the means of the groups.
### Assumptions of ANOVA 1. Normality of residuals within each group: If p-value<0.05, the data is not normally distributed

shapiro.test(df$value)
  1. Homogeneity of variances across groups
# Check the assumption of equal variances (homogeneity of variance) across groups 
# If p< 0.05, we can reject the null hypothesis of equal variances, meaning the variances are significantly different across groups
bartlett.test(`Q3.2` ~ group, data = age_table) # if data is normally distributed
# Levene's test for homogeneity of variance if data may not be normally distributed
library(car)
leveneTest(value ~ group, data = time_duration_table)

Post-hoc test

If ANOVA is significant, we can perform post-hoc tests to determine which groups are significantly different from each other.

# post-hoc test
tukey_test <- TukeyHSD(anova_test)
print(tukey_test)

Null hypothesis (H₀): All group means are equal
Alternative hypothesis (H₁): At least one group mean is different

Kruskal-Wallis test

(non-parametric test)
when the dependent variable is continuous or ordinal
when the assumptions of one-way ANOVA are not met: normality and equal variances

e.g., Likert-scale responses (ordinal) ### Post-hoc test

library(FSA)

dunnTest(value ~ group, data = df, method = "bonferroni")
# 

Propotion test -prop.test()

  • prop.test(): at least one group differs continuity correction?? The prop.test() function only supports alternative = “less” or “greater” when comparing a single proportion to a hypothesized value — not when comparing multiple groups.
  • pairwise.prop.test(): identifying which specific pairs of groups differ significantly in their proportions, choose the p.adjust.method = “holm” or “bonferroni” or “BH”
LS0tDQp0aXRsZTogIk5vcmEgTWFzdGVyIFByb2plY3QgRGF0YSBBbmFseXNpcyBOb3RlYm9vayINCmF1dGhvcjogIk5vcmEgTHVvIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCiMgVGFibGUgb2YgQ29udGVudHMNCjEuIFtOb3RhdGlvbl0oI25vdGF0aW9uKQ0KMi4gW0xvYWQgYW5kIHNwbGl0IHRoZSBkYXRhXSgjbG9hZC1hbmQtc3BsaXQtdGhlLWRhdGEpDQozLiBbU2NyZWVuaW5nIFF1ZXN0aW9uc10oI3NjcmVlbmluZy1xdWVzdGlvbnMpDQo0LiBbQWN0dWFsIFN1cnZleSBBbmFseXNpc10oI2FjdHVhbC1zdXJ2ZXktYW5hbHlzaXMpDQo1LiBbU3RhdGlzdGljYWwgVGVzdGluZ10oI3N0YXRpc3RpY2FsLXRlc3RpbmcpDQo2LiBbU2tld2VkIERhdGFdKCNza2V3ZWQtZGF0YSkNCjcuIFtEZWNpc2lvbi1tYWtpbmddKCNkZWNpc2lvbi1tYWtpbmcpDQoNCg0KVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4NCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLg0KDQpgYGB7cn0NCnBsb3QoY2FycykNCmBgYA0KDQpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouDQoNCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLg0KDQpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBSRUFETUUNCi0gcnVuIHRoZSBMb2FkIGFuZCBzcGxpdCB0aGUgZGF0YSBjaHVuayBmaXJzdA0KLSByZXN1bHRzIHdhcyBmaWx0ZXJlZCBiYXNlZCBvbiBRMy45IC0gd2hldGhlciByZXNwb25kZW50cyB1bmRlcnN0YW5kIHRoZSBjb25jZXB0IG9mIGluZmxhdGlvbiANCi0gISA6IFdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy5cDQoNCg0KIyBMb2FkIGFuZCBzcGxpdCB0aGUgZGF0YSA8YSBuYW1lPSJsb2FkLWFuZC1zcGxpdC10aGUtZGF0YSI+PC9hPg0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoRlNBKQ0KbGlicmFyeShjYXIpDQoNCg0KDQpleHBvcnRlZF9kYXRhIDwtIHJlYWRfY3N2KCJmaW5hbF9yYXdkYXRhX3ZhbHVlXzE2MDUuY3N2IikNCmV4cG9ydGVkX2RhdGEgPC0gc3Vic2V0KGV4cG9ydGVkX2RhdGEsIHNlbGVjdCA9IC1jKFN0YXJ0RGF0ZSxFbmREYXRlLFN0YXR1cyxJUEFkZHJlc3MsUHJvZ3Jlc3MsRmluaXNoZWQsUmVjb3JkZWREYXRlLCBSZWNpcGllbnRMYXN0TmFtZSxSZWNpcGllbnRGaXJzdE5hbWUsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlY2lwaWVudEVtYWlsLEV4dGVybmFsUmVmZXJlbmNlLExvY2F0aW9uTGF0aXR1ZGUsTG9jYXRpb25Mb25naXR1ZGUsRGlzdHJpYnV0aW9uQ2hhbm5lbCxVc2VyTGFuZ3VhZ2UpKQ0KcmF3ZGF0YV92YWx1ZSA8LSBzdWJzZXQoZXhwb3J0ZWRfZGF0YSwgc2VsZWN0ID0tYyhSZXNwb25zZUlkLFExLjEsUTIuMSkpDQpyYXdkYXRhX3ZhbHVlIDwtIHJhd2RhdGFfdmFsdWVbMzpucm93KHJhd2RhdGFfdmFsdWUpLCBdDQoNCiMgbGFiZWwgdGhlIGdyb3VwDQpyYXdkYXRhX3ZhbHVlIDwtIHJhd2RhdGFfdmFsdWUgJT4lDQogIG11dGF0ZShncm91cCA9IGNhc2Vfd2hlbigNCiAgICAhaXMubmEoUTQuMikgIH4gJzAtY29udHJvbGxlZCcsDQogICAgIWlzLm5hKFE2LjIpICB+ICcxLWVycm9yYmFyJywNCiAgICAhaXMubmEoUTguMikgIH4gJzItc2hhZGVkYmFyJywNCiAgICAhaXMubmEoUTEwLjIpIH4gJzMtZmFuY2hhcnRzbGljZScsDQogICAgIWlzLm5hKFExMi4yKSB+ICc0LWJlbGxjdXJ2ZScNCiAgKSkNCiMgY3JlYXRlIGEgY29weSBvZiB0aGUgZGF0YSBmb3IgUTMuOSBhbmFseXNpcw0KcmF3ZGF0YV9xM185IDwtIHJhd2RhdGFfdmFsdWUNCiMgZmlsdGVyIHBhcnRpY2lwYW50cyB3aG8gZG8gbm90IHVuZGVyc3RhbmQgdGhlIGNvbmNlcHQgb2YgaW5mbGF0aW9uDQpyYXdkYXRhX3ZhbHVlIDwtIHJhd2RhdGFfdmFsdWVbcmF3ZGF0YV92YWx1ZSRRMy45ID09ICI0IiwgXQ0KDQojIHJhd2RhdGFfdmFsdWUgPC0gcmF3ZGF0YV92YWx1ZSAlPiUNCiMgICBtdXRhdGUoZ3JvdXAgPSBjYXNlX3doZW4oDQojICAgICAhaXMubmEoUTQuMikgIH4gMCwNCiMgICAgICFpcy5uYShRNi4yKSAgfiAxLA0KIyAgICAgIWlzLm5hKFE4LjIpICB+IDIsDQojICAgICAhaXMubmEoUTEwLjIpIH4gMywNCiMgICAgICFpcy5uYShRMTIuMikgfiA0DQojICAgKSkNCg0KIyBtZXRhLWRhdGENCnRvdGFsX3Jlc3BvbmRlbnRzIDwtIG5yb3cocmF3ZGF0YV92YWx1ZSkNCg0KDQpncm91cF90b3RhbCA8LSByYXdkYXRhX3ZhbHVlICU+JQ0KICBncm91cF9ieShncm91cCkgJT4lDQogIHN1bW1hcmlzZShuX3Jlc3BvbmRlbnRzID0gbigpKQ0KDQp0b3RhbF90cmVhdG1lbnRfcmVzcG9kZW50cyA8LSB0b3RhbF9yZXNwb25kZW50cyAtIGdyb3VwX3RvdGFsJG5fcmVzcG9uZGVudHNbMV0NCiAgDQogIA0KIyBncmFwaCBwcmVwYXJhdGlvbg0KDQpsaWtlbGlob29kX2xhYmVscyA9IGMoDQogICAgIjkiID0gIkV4Y2VwdGlvbmFsbHkgdW5saWtlbHkiLA0KICAgICIxMCIgPSAiVmVyeSB1bmxpa2VseSIsDQogICAgIjExIiA9ICJRdWl0ZSB1bmxpa2VseSIsDQogICAgIjEyIiA9ICJGaWZ0eS1maWZ0eSIsDQogICAgIjEzIiA9ICJRdWl0ZSBsaWtlbHkiLA0KICAgICIxNCIgPSAiVmVyeSBsaWtlbHkiLA0KICAgICIxNSIgPSAiVmlydHVhbGx5IGNlcnRhaW4iDQogICkNCg0KIyBmaWx0ZXIgdHJlYXRtZW50IGdyb3Vwcw0KY29udHJvbGxlZF9ncm91cCA8LSByYXdkYXRhX3ZhbHVlWyFpcy5uYShyYXdkYXRhX3ZhbHVlJFE0LjIpLCBdDQplcnJvcl9iYXIgPC1yYXdkYXRhX3ZhbHVlWyFpcy5uYShyYXdkYXRhX3ZhbHVlJFE2LjIpLCBdDQpzaGFkZWRfYmFyIDwtcmF3ZGF0YV92YWx1ZVshaXMubmEocmF3ZGF0YV92YWx1ZSRROC4yKSwgXQ0KZmFuY2hhcnRfc2xpY2UgPC1yYXdkYXRhX3ZhbHVlWyFpcy5uYShyYXdkYXRhX3ZhbHVlJFExMC4yKSwgXQ0KYmVsbF9jdXJ2ZSA8LXJhd2RhdGFfdmFsdWVbIWlzLm5hKHJhd2RhdGFfdmFsdWUkUTEyLjIpLCBdDQoNCiMgYWRkaW5nIGxhYmVscyB0byB0aGUgZ3JvdXBzDQojIGNvbnRyb2xsZWRfZ3JvdXAkZ3JvdXAgPC0gMQ0KIyBlcnJvcl9iYXIkZ3JvdXAgPC0gMg0KIyBzaGFkZWRfYmFyJGdyb3VwIDwtIDMNCiMgZmFuY2hhcnRfc2xpY2UkZ3JvdXAgPC0gNA0KIyBiZWxsX2N1cnZlJGdyb3VwIDwtIDUNCg0KDQojIHJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW5zDQpjb250cm9sbGVkX2dyb3VwID0gY29udHJvbGxlZF9ncm91cFssZ3JlcGwoIl4oUTN8UTR8UTUpIixuYW1lcyhjb250cm9sbGVkX2dyb3VwKSl8bmFtZXMoY29udHJvbGxlZF9ncm91cCkgJWluJSBjKCJEdXJhdGlvbiAoaW4gc2Vjb25kcykiLCAiZ3JvdXAiKV0NCmVycm9yX2JhciA9IGVycm9yX2JhclssZ3JlcGwoIl4oUTN8UTZ8UTcpIixuYW1lcyhlcnJvcl9iYXIpKXwgbmFtZXMoZXJyb3JfYmFyKSAlaW4lIGMoIkR1cmF0aW9uIChpbiBzZWNvbmRzKSIsICJncm91cCIpXQ0Kc2hhZGVkX2JhciA9IHNoYWRlZF9iYXJbLGdyZXBsKCJeKFEzfFE4fFE5KSIsbmFtZXMoc2hhZGVkX2JhcikpfCBuYW1lcyhzaGFkZWRfYmFyKSVpbiUgYygiRHVyYXRpb24gKGluIHNlY29uZHMpIiwgImdyb3VwIildDQpmYW5jaGFydF9zbGljZSA9IGZhbmNoYXJ0X3NsaWNlWyxncmVwbCgiXihRM3xRMTB8UTExKSIsbmFtZXMoZmFuY2hhcnRfc2xpY2UpKXwgbmFtZXMoZmFuY2hhcnRfc2xpY2UpICVpbiUgYygiRHVyYXRpb24gKGluIHNlY29uZHMpIiwgImdyb3VwIildDQpiZWxsX2N1cnZlID0gYmVsbF9jdXJ2ZVssZ3JlcGwoIl4oUTN8UTEyfFExMykiLG5hbWVzKGJlbGxfY3VydmUpKXwgbmFtZXMoYmVsbF9jdXJ2ZSkgJWluJSBjKCJEdXJhdGlvbiAoaW4gc2Vjb25kcykiLCAiZ3JvdXAiKV0NCiMgY29udHJvbGxlZF9ncm91cCA9IGNvbnRyb2xsZWRfZ3JvdXBbLCFzYXBwbHkoY29udHJvbGxlZF9ncm91cCwgZnVuY3Rpb24oeCkgbWVhbihpcy5uYSh4KSkpPjAuOV0NCg0KZ3JvdXBfbGlzdCA8LSBsaXN0KA0KICBjb250cm9sbGVkID0gY29udHJvbGxlZF9ncm91cCwNCiAgZXJyb3JiYXIgPSBlcnJvcl9iYXIsDQogIHNoYWRlZGJhciA9IHNoYWRlZF9iYXIsDQogIGZhbmNoYXJ0c2xpY2UgPSBmYW5jaGFydF9zbGljZSwNCiAgYmVsbGN1cnZlID0gYmVsbF9jdXJ2ZQ0KKQ0KDQpza2V3ZWRfZ3JvdXBfbGlzdCA8LSBncm91cF9saXN0Wy0xXQ0KDQpgYGANCg0KIA0KIyBTY3JlZW5pbmcgUXVlc3Rpb25zIDxhIG5hbWU9InNjcmVlbmluZy1xdWVzdGlvbnMiPjwvYT4NCg0KIyMgISBUaW1lIER1cmF0aW9uDQpWYXJpYWJsZTogY29udGludW91cyA8YnI+IA0KTWV0aG9kOiBjaGVjayBub3JtYWxpdHkgKyBrcnVza2FsLXdhbGxpcyB0ZXN0ICsgcG9zdC1ob2MgdGVzdFwNCioqUmVzdWx0OiBwXDwgMC4wNS0tXD4gd2UgY2FuIHJlamVjdCB0aGUgaHlwb3RoZXNpcyoqIDxicj4gY29udHJvbGxlZCBncm91cCBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIChlcnJvciBiYXI7IHNoYWRlZCBiYXI7IGZhbmNoYXJ0IHNsaWNlOyBCVVQgTk9UIGZhbmNoYXJ0c2xpY2UpDQpgYGB7cn0NCnRpbWVfZHVyYXRpb25fdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVssYygiRHVyYXRpb24gKGluIHNlY29uZHMpIiwgImdyb3VwIildDQp0aW1lX2R1cmF0aW9uX3RhYmxlJGBEdXJhdGlvbiAoaW4gbWlucylgIDwtIGFzLm51bWVyaWModGltZV9kdXJhdGlvbl90YWJsZSRgRHVyYXRpb24gKGluIHNlY29uZHMpYCkvNjANCg0KIyByZXBvcnQgcXVhbnRpbGUgaW5mb3JtYXRpb24NCnN1bW1hcnkodGltZV9kdXJhdGlvbl90YWJsZSRgRHVyYXRpb24gKGluIG1pbnMpYCkNCg0KDQojIHRlc3QgZm9yIG5vcm1hbGl0eSAtLT4gSXQncyBkZWZpbml0ZWx5IG5vdCBub3JtYWwgZGlzdHJpYnV0aW9uDQojIHNoYXBpcm8udGVzdCh0aW1lX2R1cmF0aW9uX3RhYmxlJGBEdXJhdGlvbiAoaW4gbWlucylgKQ0KDQojIHJ1biB0aGUga3J1c2thbC13YWxsaXMgdGVzdA0Ka3J1c2thbF90ZXN0IDwtIGtydXNrYWwudGVzdChgRHVyYXRpb24gKGluIG1pbnMpYCB+IGdyb3VwLCBkYXRhID0gdGltZV9kdXJhdGlvbl90YWJsZSkNCnByaW50KGtydXNrYWxfdGVzdCkNCg0KIyBydW4gcG9zdC1ob2MgdGVzdA0KZHVubl90ZXN0IDwtIGR1bm5UZXN0KGBEdXJhdGlvbiAoaW4gbWlucylgIH4gZ3JvdXAsIGRhdGEgPSB0aW1lX2R1cmF0aW9uX3RhYmxlLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQpwcmludChkdW5uX3Rlc3QpDQoNCmBgYA0KDQpUaW1lIGR1cmF0aW9uIHN1bW1hcnkgdGFibGUNCg0KYGBge3J9DQp0aW1lX2R1cmF0aW9uX3N1bW1hcnkgPC0gdGltZV9kdXJhdGlvbl90YWJsZSAlPiUNCiAgZ3JvdXBfYnkoZ3JvdXApICU+JQ0KICBzdW1tYXJpc2UobWVhbl9kdXJhdGlvbiA9IG1lYW4oYER1cmF0aW9uIChpbiBtaW5zKWAsIG5hLnJtID0gVFJVRSksIA0KICAgICAgICAgICAgc2RfZHVyYXRpb24gPSBzZChgRHVyYXRpb24gKGluIG1pbnMpYCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAnZHJvcCcpDQpgYGANCg0KUGxvdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0KIyBkZW5zaXR5IHBsb3QNCmdncGxvdCh0aW1lX2R1cmF0aW9uX3RhYmxlLCBhZXMoeCA9IGBEdXJhdGlvbiAoaW4gbWlucylgLCBmaWxsID0gZ3JvdXApKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuMykgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCwgc2NhbGVzID0gImZyZWUiKSArDQogIGxhYnModGl0bGUgPSAiRHVyYXRpb24gRGVuc2l0eSBieSBHcm91cCIsDQogICAgICAgeCA9ICJEdXJhdGlvbiIsDQogICAgICAgeSA9ICJEZW5zaXR5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KDQojIGhpc3RvZ3JhbQ0KZ2dwbG90KHRpbWVfZHVyYXRpb25fdGFibGUsIGFlcyh4ID0gYER1cmF0aW9uIChpbiBtaW5zKWApKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIER1cmF0aW9uIGJ5IEdyb3VwIiwNCiAgICAgICB4ID0gIkR1cmF0aW9uIChlLmcuIGluIG1pbnV0ZXMpIiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIG1heCh0aW1lX2R1cmF0aW9uX3RhYmxlJGBEdXJhdGlvbiAoaW4gbWlucylgLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEwKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCg0KUGxvdCB0aW1lIGR1cmF0aW9uIGJhciBjaGFydC4gSXQncyBub3QgdmFsaWQgYXMgdGhlIGRhdGEgaXMgbm90IG5vcm1hbCBkaXN0cmlidXRpb24uDQoNCmBgYHtyfQ0KZ2dwbG90KHRpbWVfZHVyYXRpb25fc3VtbWFyeSwgYWVzKHggPSBncm91cCwgeSA9IG1lYW5fZHVyYXRpb24pKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInN0ZWVsYmx1ZSIsIHdpZHRoID0gMC42KSArDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX2R1cmF0aW9uIC0gc2RfZHVyYXRpb24sIHltYXggPSBtZWFuX2R1cmF0aW9uICsgc2RfZHVyYXRpb24pLCB3aWR0aCA9IDAuMikgKw0KICBsYWJzKHRpdGxlID0gIlJlc3BvbnNlIER1cmF0aW9uIGJ5IEdyb3VwIiwNCiAgICAgICB5ID0gIkR1cmF0aW9uIChpbiBtaW51dGVzKSIsDQogICAgICAgeCA9ICJHcm91cCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KIyMgUTMuMiBBZ2UNCldoYXQgaXMgeW91ciBhZ2U/IDxicj4gDQpWYXJpYWJsZTogY29udGludW91cyA8YnI+IA0KTWV0aG9kOiBrcnVza2FsLXdhbGxpcyB0ZXN0IDxicj4gDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCmFnZV90YWJsZSA8LSByYXdkYXRhX3ZhbHVlWywgYygiUTMuMiIsICJncm91cCIpXQ0KYWdlX3RhYmxlJGBRMy4yYCA8LSBhcy5udW1lcmljKGdzdWIoIlteMC05Ll0iLCAiIiwgYWdlX3RhYmxlJGBRMy4yYCkpDQoNCiMgdGVzdCBmb3Igbm9ybWFsaXR5DQojIHNoYXBpcm8udGVzdChhZ2VfdGFibGUkYFEzLjJgKQ0KIyBiYXJ0bGV0dC50ZXN0KGBRMy4yYCB+IGdyb3VwLCBkYXRhID0gYWdlX3RhYmxlKQ0KDQoNCiMgcnVuIHRoZSBrcnVza2FsLXdhbGxpcyB0ZXN0DQprcnVza2FsX3Rlc3QgPC0ga3J1c2thbC50ZXN0KGBRMy4yYCB+IGdyb3VwLCBkYXRhID0gYWdlX3RhYmxlKQ0KcHJpbnQoa3J1c2thbF90ZXN0KQ0KDQphZ2Vfc3VtbWFyeSA8LSBhZ2VfdGFibGUgJT4lDQogIGdyb3VwX2J5KGdyb3VwKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fYWdlID0gbWVhbihgUTMuMmAsIG5hLnJtID0gVFJVRSksIA0KICAgICAgICAgICAgc2RfYWdlID0gc2QoYFEzLjJgLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgLmdyb3VwcyA9ICdkcm9wJykNCmBgYA0KDQojIyBRMy4zIEdlbmRlcg0KV2hpY2ggb2YgdGhlIGZvbGxvd2luZyBiZXN0IGRlc2NyaWJlcyB5b3VyIGdlbmRlciBpZGVudGl0eT8gPGJyPiANClZhcmlhYmxlOiBjYXRlZ29yaWNhbCA8YnI+IA0KTWV0aG9kOiBjb250aW5nZW5jeSBUYWJsZSArIGNoaS1zcXVhcmVkIHRlc3QgPGJyPiANCioqUmVzdWx0OiBGYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzKioNCmBgYHtyfQ0KcTNfM190YWJsZSA8LSByYXdkYXRhX3ZhbHVlWywgYygiUTMuMyIsICJncm91cCIpXQ0KIyBxM18zX3RhYmxlJFEzLjMgPC0gcmVjb2RlKHEzXzNfdGFibGUkUTMuMywNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjEiID0gIk1hbGUiLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSAiRmVtYWxlIiwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSAiT3RoZXIiKQ0KcTNfM19jb250aW5nZW5jeSA8LSB0YWJsZShxM18zX3RhYmxlJFEzLjMsIHEzXzNfdGFibGUkZ3JvdXApDQpwcmludChxM18zX2NvbnRpbmdlbmN5KQ0KDQojIENoaS1zcXVhcmVkIHRlc3QNCmNoaXNxLnRlc3QocTNfM19jb250aW5nZW5jeSkNCg0KYGBgDQoNCkNhbGN1bGF0ZSB0aGUgZ2VuZGVyIHBlcmNlbnRhZ2UNCg0KYGBge3J9DQojIHBlcmNlbnRhZ2Ugb2YgbWFsZQ0KbWFsZV9wZXIgPC0gcTNfM19jb250aW5nZW5jeVsxLF0NCmdlbmRlcl9ncm91cF90b3RhbCA8LSBjb2xTdW1zKHEzXzNfY29udGluZ2VuY3kpDQptYWxlX3Byb3AgPC0gbWFsZV9wZXIvZ2VuZGVyX2dyb3VwX3RvdGFsDQoNCmBgYA0KDQojIyBRMy40IEhpZ2hlc3QgRWR1Y2F0aW9uDQpXaGF0IGlzIHlvdXIgaGlnaGVzdCBsZXZlbCBvZiBlZHVjYXRpb24gYWNoaWV2ZWQ/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsIHdpdGggd3JpdHRlbiBpbnNpZ2h0cyBmcm9tIGNob2ljZSA5DQpNZXRob2Q6IGNvbnRpbmdlbmN5IFRhYmxlICsgY2hpLXNxdWFyZWQgdGVzdFwNCioqUmVzdWx0OiBGYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzKioNCg0KYGBge3J9DQpxM180X3RhYmxlIDwtIHJhd2RhdGFfdmFsdWVbcmF3ZGF0YV92YWx1ZSRgUTMuNGAgIT0gIjkiLCBjKCJRMy40IiwgImdyb3VwIildDQoNCnEzXzRfY29udGluZ2VuY3kgPC0gdGFibGUocTNfNF90YWJsZSRRMy40LCBxM180X3RhYmxlJGdyb3VwKQ0KIyBDaGktc3F1YXJlZCB0ZXN0DQpjaGlzcS50ZXN0KHEzXzRfY29udGluZ2VuY3kpDQoNCmBgYA0KSGlnaGVzdCBFZHVjYXRpb24gTGV2ZWwgcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQoNCnEzXzRfcHJvcCAgPC0gYXMuZGF0YS5mcmFtZShxM180X2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMocTNfNF9wcm9wKSA8LSBjKCJRMy40IiwgIkdyb3VwIiwgIkNvdW50IikNCg0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnEzXzRfcHJvcCA8LSBxM180X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQoNCmdncGxvdChxM180X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBRMy40YCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH4gR3JvdXApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJRMy40IEhpZ2hlc3QgRWR1Y2F0aW9uIExldmVsIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICMgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKA0KICAjICAgIjEiID0gIk5vIGZvcm1hbCBlZHVjYXRpb24iLA0KICAjICAgIjIiID0gIlByaW1hcnkvRWxlbWVudGFyeSIsDQogICMgICAiMyIgPSAiU2Vjb25kYXJ5IFNjaG9vbCAoR0NTRSkiLA0KICAjICAgIjQiID0gIkhpZ2ggU2Nob29sIChBIExldmVsKSIsDQogICMgICAiNSIgPSAiVGVjaG5pY2FsIG9yIFZvY2F0aW9uYWwiLA0KICAjICAgIjYiID0gIkJhY2hlbG9ycyBvciBlcXVpdmFsZW50IGRlZ3JlZSBsZXZlbCBxdWFsaWZpY2F0aW9uIiwNCiAgIyAgICI3IiA9ICJNYXN0ZXJzIG9yIGVxdWl2YWxlbnQgaGlnaGVyIGRlZ3JlZSBsZXZlbCBxdWFsaWZpY2F0aW9uIiwNCiAgIyAgICI4IiA9ICJQaEQgb3IgZXF1aXZhbGVudCBkb2N0b3JhbCBsZXZlbCBxdWFsaWZpY2F0aW9uIikpKw0KICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQpQbG90IHBpZSBjaGFydCBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQpxM180X3RhYmxlIDwtIHJhd2RhdGFfdmFsdWVbLCBjKCJRMy40IiwgImdyb3VwIildDQoNCiMgUTMuNCBzdW1tYXJ5IHRhYmxlDQpxM180X3N1bW1hcnkgPC0gcTNfNF90YWJsZSAlPiUNCiAgZ3JvdXBfYnkoYFEzLjRgKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSBjb3VudCAvIHN1bShjb3VudCksDQogICAgICAgICBsYWJlbCA9IA0KICAgICAgICAgICAgY2FzZV93aGVuKA0KICAgICAgICAgICAgICBRMy40ID09ICIxIiB+ICIxLU5vIGZvcm1hbCBlZHVjYXRpb24iLA0KICAgICAgICAgICAgICBRMy40ID09ICIyIiB+ICIyLVByaW1hcnkvRWxlbWVudGFyeSIsDQogICAgICAgICAgICAgIFEzLjQgPT0gIjMiIH4gIjMtU2Vjb25kYXJ5IFNjaG9vbCAoR0NTRSkiLA0KICAgICAgICAgICAgICBRMy40ID09ICI0IiB+ICI0LUhpZ2ggU2Nob29sIChBIExldmVsKSIsDQogICAgICAgICAgICAgIFEzLjQgPT0gIjUiIH4gIjUtVGVjaG5pY2FsIG9yIFZvY2F0aW9uYWwiLA0KICAgICAgICAgICAgICBRMy40ID09ICI2IiB+ICI2LUJhY2hlbG9ycyBvciBlcXVpdmFsZW50IGRlZ3JlZSBsZXZlbCBxdWFsaWZpY2F0aW9uIiwNCiAgICAgICAgICAgICAgUTMuNCA9PSAiNyIgfiAiNy1NYXN0ZXJzIG9yIGVxdWl2YWxlbnQgaGlnaGVyIGRlZ3JlZSBsZXZlbCBxdWFsaWZpY2F0aW9uIiwNCiAgICAgICAgICAgICAgUTMuNCA9PSAiOCIgfiAiOC1QaEQgb3IgZXF1aXZhbGVudCBkb2N0b3JhbCBsZXZlbCBxdWFsaWZpY2F0aW9uIiwNCiAgICAgICAgICAgICAgUTMuNCA9PSAiOSIgfiAiOS1PdGhlciINCiAgICAgICAgICAgICksDQogICAgICAgICBsYWJlbCA9IHBhc3RlMChsYWJlbCwgIiAoIiwgcm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMiksICIgJSkiKQ0KICAgICAgICAgKQ0KDQpnZ3Bsb3QocTNfNF9zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gbGFiZWwpKSArDQogIGdlb21fY29sKHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICBsYWJzKHRpdGxlID0gIlEzLjQgSGlnaGVzdCBFZHVjYXRpb24gTGV2ZWwgU3VtbWFyeSBQaWUgQ2hhcnQiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQoNCmBgYA0KDQoNCg0KIyMgUTMuNSBFbXBsb3llZSBTdGF0dXMNCldoYXQgaXMgeW91ciBjdXJyZW50IHByb2Zlc3Npb24gb3IgZW1wbG95bWVudCBzdGF0dXM/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSBUYWJsZSArIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCnEzXzVfdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVtyYXdkYXRhX3ZhbHVlJGBRMy41YCAhPSAiNiIsIGMoIlEzLjUiLCAiZ3JvdXAiKV0NCnEzXzVfY29udGluZ2VuY3kgPC0gdGFibGUocTNfNV90YWJsZSRRMy41LCBxM181X3RhYmxlJGdyb3VwKQ0KIyBwcmludChxM181X2NvbnRpbmdlbmN5KQ0KDQojIENoaS1zcXVhcmVkIHRlc3QNCmNoaXNxLnRlc3QocTNfNV9jb250aW5nZW5jeSkNCg0KYGBgDQoNCkVtcGxveWVlIHN0YXR1cyBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQoNCmBgYHtyfQ0KcTNfNV9wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHEzXzVfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhxM181X3Byb3ApIDwtIGMoIlEzLjUiLCAiR3JvdXAiLCAiQ291bnQiKQ0KDQoNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpxM181X3Byb3AgPC0gcTNfNV9wcm9wICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gQ291bnQgLyBzdW0oQ291bnQpKQ0KDQpnZ3Bsb3QocTNfNV9wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUTMuNWApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IEdyb3VwKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+IEdyb3VwKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUTMuNSBFbXBsb3llZSBTdGF0dXMgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKA0KICAgICIxIiA9ICJTdHVkZW50IiwNCiAgICAiMiIgPSAiRW1wbG95ZWQiLA0KICAgICIzIiA9ICJTZWxmLWVtcGxveWVkIiwNCiAgICAiNCIgPSAiUmV0aXJlZCIsDQogICAgIjUiID0gIlVuZW1wbG95ZWQiDQogICkpICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KUGxvdCBwaWUgY2hhcnQgaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0KcTNfNV90YWJsZSA8LSByYXdkYXRhX3ZhbHVlWywgYygiUTMuNSIsICJncm91cCIpXQ0KcTNfNV9zdW1tYXJ5IDwtIHEzXzVfdGFibGUgJT4lDQogIGdyb3VwX2J5KGBRMy41YCkgJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lDQogIG11dGF0ZShwcm9wb3J0aW9uID0gY291bnQgLyBzdW0oY291bnQpLA0KICAgICAgICAgbGFiZWwgPSANCiAgICAgICAgICAgIGNhc2Vfd2hlbigNCiAgICAgICAgICAgICAgUTMuNSA9PSAiMSIgfiAiMS1TdHVkZW50IiwNCiAgICAgICAgICAgICAgUTMuNSA9PSAiMiIgfiAiMi1FbXBsb3llZCIsDQogICAgICAgICAgICAgIFEzLjUgPT0gIjMiIH4gIjMtU2VsZi1lbXBsb3llZCIsDQogICAgICAgICAgICAgIFEzLjUgPT0gIjQiIH4gIjQtUmV0aXJlZCIsDQogICAgICAgICAgICAgIFEzLjUgPT0gIjUiIH4gIjUtVW5lbXBsb3llZCIsDQogICAgICAgICAgICAgIFEzLjUgPT0gIjYiIH4gIjYtT3RoZXIiDQogICAgICAgICAgICApLA0KICAgICAgICAgbGFiZWwgPSBwYXN0ZTAobGFiZWwsICIgKCIsIHJvdW5kKHByb3BvcnRpb24gKiAxMDAsIDIpLCAiICUpIikNCiAgICAgICAgICkNCmdncGxvdChxM181X3N1bW1hcnksIGFlcyh4ID0gIiIseSA9IHByb3BvcnRpb24sIGZpbGwgPSBsYWJlbCkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIGxhYnModGl0bGUgPSAiUTMuNSBFbXBsb3llZSBTdGF0dXMgU3VtbWFyeSBQaWUgQ2hhcnQiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KDQoNCg0KIyMgUTMuNiBFY29ub21pY3MgRWR1Y2F0aW9uDQpJbiB3aGljaCwgaWYgYW55LCBoYXZlIHlvdSBldmVyIHN0dWRpZWQgZWNvbm9taWNzPyAoU2VsZWN0IGFsbCB0aGF0IGFwcGx5KVwNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogY29udmVydCB0byBsaXN0IGFuZCBjb3VudCArIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQoNCg0KUGxvdCBwZXJjZW50YWdlIGJhciBjaGFydCBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQpxM182X3RhYmxlIDwtIHJhd2RhdGFfdmFsdWVbLCBjKCJRMy42IiwgImdyb3VwIildDQpxM182X3RhYmxlJFEzLjYgPC0gbGFwcGx5KHEzXzZfdGFibGUkUTMuNiwgZnVuY3Rpb24oeCkgYXMubGlzdChhcy5udW1lcmljKHN0cnNwbGl0KHgsICIsIilbWzFdXSkpKQ0KDQojIGNvdW50IHRoZSBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgb2YgZWFjaCB2YWx1ZQ0KcTNfNl9zdW1tYXJ5IDwtIHEzXzZfdGFibGUgJT4lDQogIHVubmVzdChRMy42KSAlPiUNCiAgZ3JvdXBfYnkoYFEzLjZgKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSBjb3VudCAvIHRvdGFsX3Jlc3BvbmRlbnRzLA0KICAgICAgICAgbGFiZWwgPSANCiAgICAgICAgICAgIGNhc2Vfd2hlbigNCiAgICAgICAgICAgICAgUTMuNiA9PSAiMSIgfiAiMS1BdCBzY2hvb2wiLA0KICAgICAgICAgICAgICBRMy42ID09ICIyIiB+ICIyLUluIGhpZ2hlciBlZHVjYXRpb24iLA0KICAgICAgICAgICAgICBRMy42ID09ICIzIiB+ICIzLVRocm91Z2ggc2VsZi1kaXJlY3RlZCBzdHVkeSIsDQogICAgICAgICAgICAgIFEzLjYgPT0gIjQiIH4gIjQtU2VsZi1tb3RpdmF0ZWQgc3R1ZHkiLA0KICAgICAgICAgICAgICBRMy42ID09ICI1IiB+ICI1LU5ldmVyIHN0dWRpZWQgZWNvbm9taWNzIiwNCiAgICAgICAgICAgICAgUTMuNiA9PSAiNiIgfiAiNi1Eb27igJl0IGtub3cgLyBjYW7igJl0IHJlY2FsbCIsDQogICAgICAgICAgICAgIFEzLjYgPT0gIjciIH4gIjctT3RoZXIiDQogICAgICAgICAgICApKQ0KDQojIHEzXzZfc3VtbWFyeSRRMy42IDwtIGFzLm51bWVyaWMocTNfNl9zdW1tYXJ5JFEzLjYpDQpnZ3Bsb3QocTNfNl9zdW1tYXJ5LCBhZXMoeCA9IGZhY3RvcihsYWJlbCksIHkgPSBwcm9wb3J0aW9uKSkgKw0KICBnZW9tX2NvbChmaWxsID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChwcm9wb3J0aW9uICogMTAwLCAxKSwgIiUiKSksIA0KICAgICAgICAgICAgdmp1c3QgPSAtMC4zLCBzaXplID0gMy41KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQZXJjZW50YWdlIG9mIFBhcnRpY2lwYW50cyBTZWxlY3RpbmcgRWFjaCBRMy42IE9wdGlvbiIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQZXJjZW50YWdlIG9mIFBhcnRpY2lwYW50cyINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQoNCmBgYA0KDQoNCg0KDQoNCmBgYHtyfQ0KcTNfNl90YWJsZSA8LSByYXdkYXRhX3ZhbHVlWywgYygiUTMuNiIsICJncm91cCIpXQ0KcTNfNl90YWJsZSRRMy42IDwtIGxhcHBseShxM182X3RhYmxlJFEzLjYsIGZ1bmN0aW9uKHgpIGFzLmxpc3QoYXMubnVtZXJpYyhzdHJzcGxpdCh4LCAiLCIpW1sxXV0pKSkNCiMgY291bnQgdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlcyBvZiBlYWNoIHZhbHVlDQpxM182X3Byb3AgPC0gcTNfNl90YWJsZSAlPiUNCiAgdW5uZXN0KFEzLjYpICU+JQ0KICBncm91cF9ieShncm91cCwgUTMuNikgJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykNCnEzXzZfcHJvcCRRMy42IDwtIGFzLm51bWVyaWMocTNfNl9wcm9wJFEzLjYpDQoNCiMgY3JlYXRlIGEgY29udGluZ2VuY3kgdGFibGUNCnEzXzZfY29udGluZ2VuY3kgPC0geHRhYnMoY291bnQgfiBRMy42ICsgZ3JvdXAsIGRhdGEgPSBxM182X3Byb3ApDQpwcmludChxM182X2NvbnRpbmdlbmN5KQ0KDQojIENoaS1zcXVhcmVkIHRlc3QNCmNoaXNxLnRlc3QocTNfNl9jb250aW5nZW5jeSkNCg0KIyBxM182X3Rlc3QgPC1xM182X3Byb3AgJT4lDQojICAgZ3JvdXBfYnkoYFEzLjZgKSAlPiUNCiMgICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oY291bnQpLCAuZ3JvdXBzID0gImRyb3AiKQ0KDQpgYGANCg0KRWNvbm9taWNzIEVkdWNhdGlvbiBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgY29udmVydCBjb250aW5nZW5jeSB0YWJsZSB0byBkYXRhIGZyYW1lICMgY291bnQgMCBhcyB3ZWxsDQpxM182X3Byb3AgPC0gYXMuZGF0YS5mcmFtZShxM182X2NvbnRpbmdlbmN5KQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnEzXzZfcHJvcCA8LSBxM182X3Byb3AgJT4lDQogIGxlZnRfam9pbihncm91cF90b3RhbCwgYnkgPSAiZ3JvdXAiKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBGcmVxIC8gbl9yZXNwb25kZW50cykNCg0KZ2dwbG90KHEzXzZfcHJvcCwgYWVzKHggPSBmYWN0b3IoUTMuNiksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gZmFjdG9yKGdyb3VwKSkpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUTMuNiBFY29ub21pY3MgRWR1Y2F0aW9uIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KDQojIyBRMy43IEZpbmFuY2lhbCBBY3Rpdml0aWVzDQpXaGljaCBvZiB0aGUgZm9sbG93aW5nIGZpbmFuY2lhbCBhY3Rpdml0aWVzIGRvIHlvdSBhY3RpdmVseSBwYXJ0aWNpcGF0ZSBpbj8gKFNlbGVjdCBhbGwgdGhhdCBhcHBseSkgLSBTZWxlY3RlZCBDaG9pY2UgRml4ZWQgSW5jb21lIChlLmcuLCBnb3Zlcm5tZW50IGJvbmRzLCBjb3Jwb3JhdGUgYm9uZHMpXA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb252ZXJ0IHRvIGxpc3QgYW5kIGNvdW50ICsgY2hpLXNxdWFyZWQgdGVzdFwNCioqUmVzdWx0OiBGYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzKioNCmBgYHtyfQ0KcTNfN190YWJsZSA8LSByYXdkYXRhX3ZhbHVlWywgYygiUTMuNyIsICJncm91cCIpXQ0KcTNfN190YWJsZSRRMy43IDwtIGxhcHBseShxM183X3RhYmxlJFEzLjcsIGZ1bmN0aW9uKHgpIGFzLmxpc3QoYXMubnVtZXJpYyhzdHJzcGxpdCh4LCAiLCIpW1sxXV0pKSkNCiMgY291bnQgdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlcyBvZiBlYWNoIHZhbHVlIGluIGVhY2ggZ3JvdXANCnEzXzdfcHJvcCA8LSBxM183X3RhYmxlICU+JQ0KICB1bm5lc3QoUTMuNykgJT4lDQogIGdyb3VwX2J5KGdyb3VwLGBRMy43YCkgJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykNCnEzXzdfcHJvcCRRMy43IDwtIGFzLm51bWVyaWMocTNfN19wcm9wJFEzLjcpDQoNCiMgY3JlYXRlIGEgY29udGluZ2VuY3kgdGFibGUNCnEzXzdfY29udGluZ2VuY3kgPC0geHRhYnMoY291bnQgfiBgUTMuN2AgKyBncm91cCwgZGF0YSA9IHEzXzdfcHJvcCkNCnByaW50KHEzXzdfY29udGluZ2VuY3kpDQojIENoaS1zcXVhcmVkIHRlc3QNCmNoaXNxLnRlc3QocTNfN19jb250aW5nZW5jeSkNCg0KYGBgDQoNClBsb3QgZmluYW5jaWFsIGFjdGl2aXRpZXMgcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQojIGNvbnZlcnQgY29udGluZ2VuY3kgdGFibGUgdG8gZGF0YSBmcmFtZQ0KcTNfN19wcm9wIDwtIGFzLmRhdGEuZnJhbWUocTNfN19jb250aW5nZW5jeSkgJT4lDQogIGxlZnRfam9pbihncm91cF90b3RhbCwgYnkgPSAiZ3JvdXAiKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBGcmVxIC8gbl9yZXNwb25kZW50cykNCg0KDQpnZ3Bsb3QocTNfN19wcm9wLCBhZXMoeCA9IGZhY3RvcihgUTMuN2ApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IGZhY3Rvcihncm91cCkpKSArIA0KICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJRMy43IEZpbmFuY2lhbCBBY3Rpdml0aWVzIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogICAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKA0KICAgICIxMSIgPSAiU2F2aW5ncyIsDQogICAgIjEyIiA9ICJJbnZlc3RtZW50cyIsDQogICAgIjEzIiA9ICJGaXhlZCBJbmNvbWUiLA0KICAgICIxNCIgPSAiUmV0aXJlbWVudCBQbGFubmluZyIsDQogICAgIjE1IiA9ICJUcmFkaW5nIiwNCiAgICAiMTYiID0gIlJlYWwgRXN0YXRlIiwNCiAgICAiMTciID0gIkNyeXB0b2N1cnJlbmNpZXMiLA0KICAgICIxOCIgPSAiTm9uZSBvZiB0aGUgYWJvdmUiLA0KICAgICIxOSIgPSAiT3RoZXIiDQogICAgICApKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQoNCmBgYA0KUGxvdCBwZXJjZW50YWdlIGJhciBjaGFydCBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQpxM183X3N1bW1hcnkgPC1xM183X3Byb3AgJT4lDQogIGdyb3VwX2J5KGBRMy43YCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShGcmVxKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lDQogIG11dGF0ZShwcm9wb3J0aW9uID0gdG90YWxfY291bnQgLyB0b3RhbF9yZXNwb25kZW50cywNCiAgICAgICAgIGxhYmVsID0gDQogICAgICAgICAgICBjYXNlX3doZW4oDQogICAgICAgICAgICAgIGBRMy43YCA9PSAiMTEiIH4gIjExLVNhdmluZ3MiLA0KICAgICAgICAgICAgICBgUTMuN2AgPT0gIjEyIiB+ICIxMi1JbnZlc3RtZW50cyIsDQogICAgICAgICAgICAgIGBRMy43YCA9PSAiMTMiIH4gIjEzLUZpeGVkIEluY29tZSIsDQogICAgICAgICAgICAgIGBRMy43YCA9PSAiMTQiIH4gIjE0LVJldGlyZW1lbnQgUGxhbm5pbmciLA0KICAgICAgICAgICAgICBgUTMuN2AgPT0gIjE1IiB+ICIxNS1UcmFkaW5nIiwNCiAgICAgICAgICAgICAgYFEzLjdgID09ICIxNiIgfiAiMTYtUmVhbCBFc3RhdGUiLA0KICAgICAgICAgICAgICBgUTMuN2AgPT0gIjE3IiB+ICIxNy1DcnlwdG9jdXJyZW5jaWVzIiwNCiAgICAgICAgICAgICAgYFEzLjdgID09ICIxOCIgfiAiMTgtTm9uZSBvZiB0aGUgYWJvdmUiLA0KICAgICAgICAgICAgICBgUTMuN2AgPT0gIjE5IiB+ICIxOS1PdGhlciINCiAgICAgICAgICAgICkpDQoNCmdncGxvdChxM183X3N1bW1hcnksIGFlcyh4ID0gZmFjdG9yKGxhYmVsKSwgeSA9IHByb3BvcnRpb24pKSArDQogIGdlb21fY29sKGZpbGwgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKHByb3BvcnRpb24gKiAxMDAsIDEpLCAiJSIpKSwgDQogICAgICAgICAgICB2anVzdCA9IC0wLjMsIHNpemUgPSAzLjUpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBlcmNlbnRhZ2Ugb2YgUGFydGljaXBhbnRzIFNlbGVjdGluZyBFYWNoIFEzLjcgT3B0aW9uIiwNCiAgICB4ID0gIlJlc3BvbnNlIiwNCiAgICB5ID0gIlBlcmNlbnRhZ2Ugb2YgUGFydGljaXBhbnRzIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQojIyBRMy44IEF3YXJlbmVzcyBvZiBFY29ub21pY3MNCkhvdyBmcmVxdWVudGx5LCBpZiBhdCBhbGwsIGRvIHlvdSByZWFkL3dhdGNoL2xpc3RlbiB0byBuZXdzIHN0b3JpZXMgcmVsYXRlZCB0byBlY29ub21pY3Mgb3IgdGhlIGVjb25vbXk/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSArIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCnEzXzhfdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVssIGMoIlEzLjgiLCAiZ3JvdXAiKV0NCg0KcTNfOF9jb250aW5nZW5jeSA8LSB0YWJsZShxM184X3RhYmxlJFEzLjgsIHEzXzhfdGFibGUkZ3JvdXApDQpwcmludChxM184X2NvbnRpbmdlbmN5KQ0KIyBDaGktc3F1YXJlZCB0ZXN0DQojIGNoaXNxLnRlc3QocTNfOF9jb250aW5nZW5jeSkNCmNoaXNxLnRlc3QocTNfOF9jb250aW5nZW5jeVstbnJvdyhxM184X2NvbnRpbmdlbmN5KSwgXSkNCg0KYGBgDQpBd2FyZW5lc3Mgb2YgRWNvbm9taWNzIHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0KcTNfOF9wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHEzXzhfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhxM184X3Byb3ApIDwtIGMoIlEzLjgiLCAiR3JvdXAiLCAiQ291bnQiKQ0KDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0KcTNfOF9wcm9wIDwtIHEzXzhfcHJvcCAlPiUNCiAgbXV0YXRlKFEzLjhfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgUTMuOCA9PSAiMSIgfiAiMS1OZXZlciIsDQogICAgUTMuOCA9PSAiMiIgfiAiMi1SYXJlbHkiLA0KICAgIFEzLjggPT0gIjMiIH4gIjMtTW9udGhseSIsDQogICAgUTMuOCA9PSAiNCIgfiAiNC1XZWVrbHkiLA0KICAgIFEzLjggPT0gIjUiIH4gIjUtQWxtb3N0IGRhaWx5IiwNCiAgICBRMy44ID09ICI2IiB+ICI2LUV2ZXJ5IGRheSIsDQogICAgUTMuOCA9PSAiNyIgfiAiNy1Ob3Qgc3VyZSINCiAgKSkNCg0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnEzXzhfcHJvcCA8LSBxM184X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQoNCmdncGxvdChxM184X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBRMy44X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofiBHcm91cCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlEzLjggQXdhcmVuZXNzIG9mIEVjb25vbWljcyBQcm9wb3Rpb24gUGxvdCBhY3Jvc3MgR3JvdXBzIiwNCiAgICB4ID0gIlJlc3BvbnNlIiwNCiAgICB5ID0gIlByb3BvcnRpb24iDQogICkgKw0KICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNClBsb3QgcGllIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnEzXzhfc3VtbWFyeSA8LSBxM184X3Byb3AgJT4lDQogIGdyb3VwX2J5KGBRMy44X2xhYmVsYCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShDb3VudCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBtdXRhdGUocHJvcG9ydGlvbiA9IHRvdGFsX2NvdW50IC8gc3VtKHRvdGFsX2NvdW50KSwNCiAgICAgICAgYFEzLjhfbGFiZWxgID0gcGFzdGUwKGBRMy44X2xhYmVsYCwgIiAoIiwgcm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMiksICIgJSkiKSkNCmdncGxvdChxM184X3N1bW1hcnksIGFlcyh4ID0gIiIseSA9IHByb3BvcnRpb24sIGZpbGwgPSBgUTMuOF9sYWJlbGApKSArDQogIGdlb21fY29sKHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICBsYWJzKHRpdGxlID0gIlEzLjggQXdhcmVuZXNzIG9mIEVjb25vbWljcyBTdW1tYXJ5IFBpZSBDaGFydCIsDQogICAgICAgeCA9ICIiLA0KICAgICAgIHkgPSAiIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkNCmBgYA0KIyMgUTMuOSBJbmZsYXRpb24gS25vd2xlZGdlDQpUbyB0aGUgYmVzdCBvZiB5b3VyIGtub3dsZWRnZSwgd2hpY2ggb3B0aW9uIG1vc3QgYWNjdXJhdGVseSBkZXNjcmliZXMgd2hhdCBpbmZsYXRpb24gaXM/XA0KRGVmaW5pdGl2ZSBjb3JyZWN0IGFuc3dlclwNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogZGVzY3JpcHRpdmUgYW5hbHlzaXNcDQoqKlJlc3BvbmRlbnRzIHdlcmUgZmlsdGVyZWQgYmFzZWQgb24gd2hldGhlciBpZiB0aGV5IGNhbiB1bmRlcnN0YW5kIHdoYXQgaW5mbGF0aW9uIGlzLioqXA0KDQpgYGB7cn0NCnEzXzlfdGFibGUgPC0gcmF3ZGF0YV9xM185WywgYygiUTMuOSIsICJncm91cCIpXQ0KcTNfOV9zdW1tYXJ5IDwtIHEzXzlfdGFibGUgJT4lDQogIGdyb3VwX2J5KGBRMy45YCkgJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lDQogIG11dGF0ZShwcm9wb3J0aW9uID0gY291bnQgLyBzdW0oY291bnQpKQ0KDQogIGdncGxvdChxM185X3N1bW1hcnksIGFlcyh4ID0gIiIseSA9IHByb3BvcnRpb24sIGZpbGwgPSBgUTMuOWApKSArDQogIGdlb21fY29sKHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICBsYWJzKHRpdGxlID0gIlEzLjkgSW5mbGF0aW9uIEtub3dsZWRnZSBTdW1tYXJ5IFBpZSBDaGFydCIsDQogICAgICAgeCA9ICIiLA0KICAgICAgIHkgPSAiIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KYGBgDQoNCiMjIFEzLjExIFRydXN0IG9mIE9mZmljaWFsIERhdGENCkhvdyBtdWNoIGRvIHlvdSB0cnVzdCBvZmZpY2lhbCBpbmZsYXRpb24gZm9yZWNhc3RzIChGb3IgaW5zdGFuY2UsIHRoZSBmb3JlY2FzdHMgcmVsZWFzZWQgYnkgdGhlIEJhbmsgb2YgRW5nbGFuZCk/XA0KKmFzY2VuZGluZyB2YWx1ZS1pbmNyZWFzaW5nIHRydXN0ICsgZXhjbHVkZSA2LSBVbnN1cmUgLyBubyBvcGluaW9uKlwNClZhcmlhYmxlOiB0cmVhdCBhcyBjb250aW51b3VzXA0KTWV0aG9kOiBLcnVza2FsLVdhbGxpcyB0ZXN0XA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKg0KDQpgYGB7cn0NCnEzXzExX3RhYmxlIDwtIHJhd2RhdGFfdmFsdWVbcmF3ZGF0YV92YWx1ZSRgUTMuMTFgICE9ICI2IiwgYygiUTMuMTEiLCAiZ3JvdXAiKV0NCnEzXzExX3RhYmxlJFEzLjExIDwtIGFzLm51bWVyaWMocTNfMTFfdGFibGUkYFEzLjExYCkNCiMgY2hlY2sgbm9ybWFsaXR5IC0tPiBOb3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQNCiMgc2hhcGlyby50ZXN0KHEzXzExX3RhYmxlJFEzLjExKQ0KIyBiYXJ0bGV0dC50ZXN0KGBRMy4xMWAgfiBncm91cCwgZGF0YSA9IHEzXzExX3RhYmxlKQ0KDQoNCiMgcnVuIGtydXNrYWwgdGVzdA0Ka3J1c2thbF90ZXN0IDwtIGtydXNrYWwudGVzdChRMy4xMSB+IGdyb3VwLCBkYXRhID0gcTNfMTFfdGFibGUpDQpwcmludChrcnVza2FsX3Rlc3QpDQoNCnEzXzExX3N1bW1hcnkgPC0gcTNfMTFfdGFibGUgJT4lDQogIGdyb3VwX2J5KGdyb3VwKSAlPiUNCiAgc3VtbWFyaXNlKHEzXzExX21lYW4gPSBtZWFuKGFzLm51bWVyaWMoUTMuMTEpLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgcTNfMTFfc2QgPSBzZChhcy5udW1lcmljKFEzLjExKSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAnZHJvcCcpDQoNCiMgcmVwb3J0IHF1YW50aWxlIGluZm9ybWF0aW9uDQpzdW1tYXJ5KHEzXzExX3RhYmxlJFEzLjExKQ0KDQoNCg0KYGBgDQpQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQojIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KZ2dwbG90KHEzXzExX3RhYmxlLCBhZXMoeCA9IFEzLjExKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogICMgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnModGl0bGUgPSAiUTMuMTEgVHJ1c3Qgb2ZmaWNpYWwgaW5mbGF0aW9uIGZvcmVjYXN0cyBkaXN0cmlidXRpb24iLA0KICAgICAgIHggPSAiUTMuMTEiLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHEzXzExX3RhYmxlJFEzLjExLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIEdyb3VwZWQgYmFyLXN0eWxlIGhpc3RvZ3JhbQ0KZ2dwbG90KHEzXzExX3RhYmxlLCBhZXMoeCA9IGZhY3RvcihRMy4xMSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJRMy4xMSBUcnVzdCBvZmZpY2lhbCBpbmZsYXRpb24gZm9yZWNhc3RzIGRpc3RyaWJ1dGlvbiBieSBncm91cCIsDQogICAgeCA9ICJRMy4xMSBSZXNwb25zZSIsDQogICAgeSA9ICJDb3VudCIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KDQoNCiANCg0KDQojIyBRMy4xMiBGcmVxdWVuY3kgb2YgQ2hlY2tpbmcgQ3VycmVudCBJbmZsYXRpb24NCkhvdyBvZnRlbiBkbyB5b3UgY2hlY2sgdGhlIGN1cnJlbnQgdmFsdWUgb2YgaW5mbGF0aW9uPw0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSArIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0Kc3VtbWFyeShhcy5udW1lcmljKHJhd2RhdGFfdmFsdWUkUTMuMTIpKQ0KDQpxM18xMl90YWJsZSA8LSByYXdkYXRhX3ZhbHVlWywgYygiUTMuMTIiLCAiZ3JvdXAiKV0NCnEzXzEyX2NvbnRpbmdlbmN5IDwtIHRhYmxlKHEzXzEyX3RhYmxlJFEzLjEyLCBxM18xMl90YWJsZSRncm91cCkNCnByaW50KHEzXzEyX2NvbnRpbmdlbmN5KQ0KIyBDaGktc3F1YXJlZCB0ZXN0DQpjaGlzcS50ZXN0KHEzXzEyX2NvbnRpbmdlbmN5KQ0KDQpgYGANCkZyZXF1ZW5jeSBvZiBDaGVja2luZyBDdXJyZW50IEluZmxhdGlvbiBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnEzXzEyX3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUocTNfMTJfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhxM18xMl9wcm9wKSA8LSBjKCJRMy4xMiIsICJHcm91cCIsICJDb3VudCIpDQoNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpxM18xMl9wcm9wIDwtIHEzXzEyX3Byb3AgJT4lDQogIG11dGF0ZShRMy4xMl9sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBRMy4xMiA9PSAiMSIgfiAiMS1OZXZlciIsDQogICAgUTMuMTIgPT0gIjIiIH4gIjItUmFyZWx5IiwNCiAgICBRMy4xMiA9PSAiMyIgfiAiMy1Tb21ldGltZXMiLA0KICAgIFEzLjEyID09ICI0IiB+ICI0LU9mdGVuIg0KICApKQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnEzXzEyX3Byb3AgPC0gcTNfMTJfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoR3JvdXApICU+JQ0KICBtdXRhdGUoUHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkNCg0KZ2dwbG90KHEzXzEyX3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBRMy4xMl9sYWJlbGApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IEdyb3VwKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJRMy4xMiBGcmVxdWVuY3kgb2YgQ2hlY2tpbmcgQ3VycmVudCBJbmZsYXRpb24gUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCiAgDQpgYGANClBsb3QgcGllIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnEzXzEyX3N1bW1hcnkgPC0gcTNfMTJfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoYFEzLjEyX2xhYmVsYCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShDb3VudCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBtdXRhdGUocHJvcG9ydGlvbiA9IHRvdGFsX2NvdW50IC8gc3VtKHRvdGFsX2NvdW50KSwNCiAgICAgICAgIGBRMy4xMl9sYWJlbGAgPSBwYXN0ZTAoYFEzLjEyX2xhYmVsYCwgIiAoIiwgcm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMiksICIgJSkiKSkNCmdncGxvdChxM18xMl9zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gYFEzLjEyX2xhYmVsYCkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIGxhYnModGl0bGUgPSAiUTMuMTIgRnJlcXVlbmN5IG9mIENoZWNraW5nIEN1cnJlbnQgSW5mbGF0aW9uIFN1bW1hcnkgUGllIENoYXJ0IiwNCiAgICAgICB4ID0gIiIsDQogICAgICAgeSA9ICIiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCg0KIyMgUTMuMTMgU291cmNlIG9mIEN1cnJlbnQgSW5mbGF0aW9uDQpXaGljaCBzb3VyY2UgZG8geW91IHJlbHkgb24gdG8gaW5mb3JtIHlvdXJzZWxmIGFib3V0IHRoZSBjdXJyZW50IHZhbHVlIG9mIGluZmxhdGlvbj9cDQpWYXJpYWJsZTogY2F0ZWdvcmljYWxcDQpNZXRob2Q6IGNvbnZlcnQgdG8gbGlzdCBhbmQgY291bnQgKyBjaGktc3F1YXJlZCB0ZXN0XA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKg0KYGBge3J9DQpxM18xM190YWJsZSA8LSByYXdkYXRhX3ZhbHVlWywgYygiUTMuMTMiLCAiZ3JvdXAiKV0NCnEzXzEzX3RhYmxlJFEzLjEzIDwtIGxhcHBseShxM18xM190YWJsZSRRMy4xMywgZnVuY3Rpb24oeCkgYXMubGlzdChhcy5udW1lcmljKHN0cnNwbGl0KHgsICIsIilbWzFdXSkpKQ0KIyBjb3VudCB0aGUgbnVtYmVyIG9mIG9jY3VycmVuY2VzIG9mIGVhY2ggdmFsdWUNCnEzXzEzX3Byb3AgPC0gcTNfMTNfdGFibGUgJT4lDQogIHVubmVzdChRMy4xMykgJT4lDQogIGdyb3VwX2J5KGdyb3VwLGBRMy4xM2ApICU+JQ0KICBzdW1tYXJpc2UoY291bnQgPSBuKCksIC5ncm91cHMgPSAnZHJvcCcpDQpxM18xM19wcm9wJFEzLjEzIDwtIGFzLm51bWVyaWMocTNfMTNfcHJvcCRRMy4xMykNCiMgY3JlYXRlIGEgY29udGluZ2VuY3kgdGFibGUNCnEzXzEzX2NvbnRpbmdlbmN5IDwtIHh0YWJzKGNvdW50IH4gYFEzLjEzYCArIGdyb3VwLCBkYXRhID0gcTNfMTNfcHJvcCkNCnByaW50KHEzXzEzX2NvbnRpbmdlbmN5KQ0KIyBDaGktc3F1YXJlZCB0ZXN0DQpjaGlzcS50ZXN0KHEzXzEzX2NvbnRpbmdlbmN5KQ0KYGBgDQpQbG90IHNvdXJjZSBvZiBjdXJyZW50IGluZmxhdGlvbiBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgY29udmVydCBjb250aW5nZW5jeSB0YWJsZSB0byBkYXRhIGZyYW1lDQpxM18xM19wcm9wIDwtIGFzLmRhdGEuZnJhbWUocTNfMTNfY29udGluZ2VuY3kpICU+JQ0KICBsZWZ0X2pvaW4oZ3JvdXBfdG90YWwsIGJ5ID0gImdyb3VwIikgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gRnJlcSAvIG5fcmVzcG9uZGVudHMpDQoNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpxM18xM19wcm9wIDwtIHEzXzEzX3Byb3AgJT4lDQogIG11dGF0ZShRMy4xM19sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBgUTMuMTNgID09ICIxIiB+ICIxLVRlbGV2aXNpb24sIHJhZGlvIG9yIHByaW50IG1lZGlhIiwNCiAgICBgUTMuMTNgID09ICIyIiB+ICIyLVNvY2lhbCBtZWRpYSIsDQogICAgYFEzLjEzYCA9PSAiMyIgfiAiMy1PZmZpY2lhbCB3ZWJzaXRlcyBvciBkYXRhIHJlbGVhc2VzIiwNCiAgICBgUTMuMTNgID09ICI0IiB+ICI0LUNvbnRlbnQgcGxhdGZvcm0iLA0KICAgIGBRMy4xM2AgPT0gIjUiIH4gIjUtQWN0aXZlbHkgc2VhcmNoIG9uIHNlYXJjaCBlbmdpbmVzIiwNCiAgICBgUTMuMTNgID09ICI2IiB+ICI2LUZhbWlseSBvciBmcmllbmRzIiwNCiAgICBgUTMuMTNgID09ICI3IiB+ICI3LUZpbmFuY2lhbCBhZHZpY2Ugd2Vic2l0ZXMvZm9ydW1zIiwNCiAgICBgUTMuMTNgID09ICI4IiB+ICI4LVByaXZhdGUgYmFua3Mgb3IgZWNvbm9taWMgcmVzZWFyY2ggaW5zdGl0dXRlcyIsDQogICAgYFEzLjEzYCA9PSAiOSIgfiAiOS1PdGhlciINCiAgKSkNCmdncGxvdChxM18xM19wcm9wLCBhZXMoeCA9IGZhY3RvcihgUTMuMTNfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBncm91cCkpICsNCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUTMuMTMgU291cmNlIG9mIEN1cnJlbnQgSW5mbGF0aW9uIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQpgYGANClBsb3QgcGVyY2VudGFnZSBiYXIgY2hhcnQgaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0KcTNfMTNfc3VtbWFyeSA8LSBxM18xM19wcm9wICU+JQ0KICBncm91cF9ieShgUTMuMTNfbGFiZWxgKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX2NvdW50ID0gc3VtKEZyZXEpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSB0b3RhbF9jb3VudCAvIHRvdGFsX3Jlc3BvbmRlbnRzKQ0KDQpnZ3Bsb3QocTNfMTNfc3VtbWFyeSwgYWVzKHggPSBmYWN0b3IoUTMuMTNfbGFiZWwpLCB5ID0gcHJvcG9ydGlvbikpICsNCiAgZ2VvbV9jb2woZmlsbCA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMSksICIlIikpLCANCiAgICAgICAgICAgIHZqdXN0ID0gLTAuMywgc2l6ZSA9IDMuNSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUGVyY2VudGFnZSBvZiBQYXJ0aWNpcGFudHMgU2VsZWN0aW5nIEVhY2ggUTMuMTMgT3B0aW9uIiwNCiAgICB4ID0gIlJlc3BvbnNlIiwNCiAgICB5ID0gIlBlcmNlbnRhZ2Ugb2YgUGFydGljaXBhbnRzIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQojIyBRMy4xNCBJbXBhY3Qgb2YgQ3VycmVudCBJbmZsYXRpb24NClRvIHdoYXQgZXh0ZW50IGRvIHlvdSBmZWVsIHRoYXQgdGhlIGN1cnJlbnQgdmFsdWUgb2YgaW5mbGF0aW9uIGlzIGltcGFjdGluZyB5b3VyIHBlcnNvbmFsIGZpbmFuY2VzPw0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSArIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0Kc3VtbWFyeShhcy5udW1lcmljKHJhd2RhdGFfdmFsdWUkUTMuMTQpKQ0KcTNfMTRfdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVssIGMoIlEzLjE0IiwgImdyb3VwIildDQpxM18xNF9jb250aW5nZW5jeSA8LSB0YWJsZShxM18xNF90YWJsZSRRMy4xNCwgcTNfMTRfdGFibGUkZ3JvdXApDQpwcmludChxM18xNF9jb250aW5nZW5jeSkNCiMgQ2hpLXNxdWFyZWQgdGVzdA0KY2hpc3EudGVzdChxM18xNF9jb250aW5nZW5jeSkNCg0KYGBgDQpJbXBhY3Qgb2YgQ3VycmVudCBJbmZsYXRpb24gcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQpxM18xNF9wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHEzXzE0X2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMocTNfMTRfcHJvcCkgPC0gYygiUTMuMTQiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnEzXzE0X3Byb3AgPC0gcTNfMTRfcHJvcCAlPiUNCiAgbXV0YXRlKFEzLjE0X2xhYmVsID0gY2FzZV93aGVuKA0KICAgIFEzLjE0ID09ICIxIiB+ICIxLU5vdCBhdCBhbGwiLA0KICAgIFEzLjE0ID09ICIyIiB+ICIyLVNsaWdodGx5IiwNCiAgICBRMy4xNCA9PSAiMyIgfiAiMy1Nb2RlcmF0ZWx5IiwNCiAgICBRMy4xNCA9PSAiNCIgfiAiNC1WZXJ5IHNpZ25pZmljYW50bHkiDQogICkpDQojIGNhbGN1bGF0ZSBwcm9wb3J0aW9ucyB3aXRoaW4gZWFjaCBncm91cA0KcTNfMTRfcHJvcCA8LSBxM18xNF9wcm9wICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gQ291bnQgLyBzdW0oQ291bnQpKQ0KZ2dwbG90KHEzXzE0X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBRMy4xNF9sYWJlbGApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IEdyb3VwKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJRMy4xNCBJbXBhY3Qgb2YgQ3VycmVudCBJbmZsYXRpb24gUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQpQbG90IHBpZSBjaGFydCBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQpxM18xNF9zdW1tYXJ5IDwtIHEzXzE0X3Byb3AgJT4lDQogIGdyb3VwX2J5KGBRMy4xNF9sYWJlbGApICU+JQ0KICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oQ291bnQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSB0b3RhbF9jb3VudCAvIHN1bSh0b3RhbF9jb3VudCksDQogICAgICAgIGBRMy4xNF9sYWJlbGAgPSBwYXN0ZTAoYFEzLjE0X2xhYmVsYCwgIiAoIiwgcm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMiksICIgJSkiKSkNCmdncGxvdChxM18xNF9zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gYFEzLjE0X2xhYmVsYCkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIGxhYnModGl0bGUgPSAiUTMuMTQgSW1wYWN0IG9mIEN1cnJlbnQgSW5mbGF0aW9uIFN1bW1hcnkgUGllIENoYXJ0IiwNCiAgICAgICB4ID0gIiIsDQogICAgICAgeSA9ICIiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCiMjIFEzLjE1IFJlc3BvbnNlIHRvIEN1cnJlbnQgSW5mbGF0aW9uDQpIb3cgbXVjaCBkbyB5b3UgYWRqdXN0IG9yIHRha2UgYWN0aW9uIGluIHJlc3BvbnNlIHRvIHRoZSBjaGFuZ2UgaW4gY3VycmVudCB2YWx1ZSBvZiBpbmZsYXRpb24/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSArIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0Kc3VtbWFyeShhcy5udW1lcmljKHJhd2RhdGFfdmFsdWUkUTMuMTUpKQ0KcTNfMTVfdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVssIGMoIlEzLjE1IiwgImdyb3VwIildDQpxM18xNV9jb250aW5nZW5jeSA8LSB0YWJsZShxM18xNV90YWJsZSRRMy4xNSwgcTNfMTVfdGFibGUkZ3JvdXApDQpwcmludChxM18xNV9jb250aW5nZW5jeSkNCiMgQ2hpLXNxdWFyZWQgdGVzdA0KY2hpc3EudGVzdChxM18xNV9jb250aW5nZW5jeSkNCg0KYGBgDQpSZXNwb25zZSB0byBDdXJyZW50IEluZmxhdGlvbiBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnEzXzE1X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUocTNfMTVfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhxM18xNV9wcm9wKSA8LSBjKCJRMy4xNSIsICJHcm91cCIsICJDb3VudCIpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0KcTNfMTVfcHJvcCA8LSBxM18xNV9wcm9wICU+JQ0KICBtdXRhdGUoUTMuMTVfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgUTMuMTUgPT0gIjEiIH4gIjEtTm90IGF0IGFsbCIsDQogICAgUTMuMTUgPT0gIjIiIH4gIjItUmFyZWx5IiwNCiAgICBRMy4xNSA9PSAiMyIgfiAiMy1Tb21ld2hhdCBhY3RpdmVseSIsDQogICAgUTMuMTUgPT0gIjQiIH4gIjQtVmVyeSBhY3RpdmVseSINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpxM18xNV9wcm9wIDwtIHEzXzE1X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3QocTNfMTVfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYFEzLjE1X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlEzLjE1IFJlc3BvbnNlIHRvIEN1cnJlbnQgSW5mbGF0aW9uIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgcGllIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnEzXzE1X3N1bW1hcnkgPC0gcTNfMTVfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoYFEzLjE1X2xhYmVsYCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShDb3VudCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBtdXRhdGUocHJvcG9ydGlvbiA9IHRvdGFsX2NvdW50IC8gc3VtKHRvdGFsX2NvdW50KSwNCiAgICAgICAgIGBRMy4xNV9ncmFwaF9sYWJlbGAgPSBwYXN0ZTAoYFEzLjE1X2xhYmVsYCwgIiAoIiwgcm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMiksICIgJSkiKSkNCmdncGxvdChxM18xNV9zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gYFEzLjE1X2dyYXBoX2xhYmVsYCkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIGxhYnModGl0bGUgPSAiUTMuMTUgUmVzcG9uc2UgdG8gQ3VycmVudCBJbmZsYXRpb24gU3VtbWFyeSBQaWUgQ2hhcnQiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQoNCmBgYA0KDQojIyBRMy4xNiBGcmVxdWVuY3kgb2YgQ2hlY2tpbmcgSW5mbGF0aW9uIEZvcmVjYXN0cw0KSG93IG9mdGVuIGRvIHlvdSBsb29rIGF0IGluZmxhdGlvbiBmb3JlY2FzdHMgKHRoYXQgaXMsIGluZm9ybWF0aW9uIGFib3V0IGZ1dHVyZSBpbmZsYXRpb24pP1wNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgKyBjaGktc3F1YXJlZCB0ZXN0XA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKg0KYGBge3J9DQojIEluaXRpYWwgQ2hlY2sNCnN1bW1hcnkoYXMubnVtZXJpYyhyYXdkYXRhX3ZhbHVlJFEzLjE2KSkNCg0KcTNfMTZfdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVssIGMoIlEzLjE2IiwgImdyb3VwIildDQpxM18xNl9jb250aW5nZW5jeSA8LSB0YWJsZShxM18xNl90YWJsZSRRMy4xNiwgcTNfMTZfdGFibGUkZ3JvdXApDQpwcmludChxM18xNl9jb250aW5nZW5jeSkNCiMgQ2hpLXNxdWFyZWQgdGVzdA0KY2hpc3EudGVzdChxM18xNl9jb250aW5nZW5jeSkNCg0KYGBgDQpGcmVxdWVuY3kgb2YgQ2hlY2tpbmcgSW5mbGF0aW9uIEZvcmVjYXN0cyBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnEzXzE2X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUocTNfMTZfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhxM18xNl9wcm9wKSA8LSBjKCJRMy4xNiIsICJHcm91cCIsICJDb3VudCIpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0KcTNfMTZfcHJvcCA8LSBxM18xNl9wcm9wICU+JQ0KICBtdXRhdGUoUTMuMTZfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgUTMuMTYgPT0gIjEiIH4gIjEtTmV2ZXIiLA0KICAgIFEzLjE2ID09ICIyIiB+ICIyLVJhcmVseSIsDQogICAgUTMuMTYgPT0gIjMiIH4gIjMtU29tZXRpbWVzIiwNCiAgICBRMy4xNiA9PSAiNCIgfiAiNC1PZnRlbiINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpxM18xNl9wcm9wIDwtIHEzXzE2X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3QocTNfMTZfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYFEzLjE2X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlEzLjE2IEZyZXF1ZW5jeSBvZiBDaGVja2luZyBJbmZsYXRpb24gRm9yZWNhc3RzIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgcGllIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnEzXzE2X3N1bW1hcnkgPC0gcTNfMTZfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoYFEzLjE2X2xhYmVsYCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShDb3VudCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBtdXRhdGUocHJvcG9ydGlvbiA9IHRvdGFsX2NvdW50IC8gc3VtKHRvdGFsX2NvdW50KSwNCiAgICAgICAgIGBRMy4xNl9sYWJlbGAgPSBwYXN0ZTAoYFEzLjE2X2xhYmVsYCwgIiAoIiwgcm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMiksICIgJSkiKSkNCmdncGxvdChxM18xNl9zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gYFEzLjE2X2xhYmVsYCkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAxKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIGxhYnModGl0bGUgPSAiUTMuMTYgRnJlcXVlbmN5IG9mIENoZWNraW5nIEluZmxhdGlvbiBGb3JlY2FzdHMgU3VtbWFyeSBQaWUgQ2hhcnQiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KIyMgUTMuMTcgU291cmNlIG9mIEluZmxhdGlvbiBGb3JlY2FzdHMNCldoaWNoIHNvdXJjZSBkbyB5b3UgcmVseSBvbiB0byBvYnRhaW4gaW5mbGF0aW9uIGZvcmVjYXN0cyAoaW5mb3JtYXRpb24gYWJvdXQgZnV0dXJlIGluZmxhdGlvbik/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb252ZXJ0IHRvIGxpc3QgYW5kIGNvdW50ICsgY2hpLXNxdWFyZWQgdGVzdFwNCioqUmVzdWx0OiBGYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzKioNCmBgYHtyfQ0KcTNfMTdfdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVssIGMoIlEzLjE3IiwgImdyb3VwIildDQpxM18xN190YWJsZSRRMy4xNyA8LSBsYXBwbHkocTNfMTdfdGFibGUkUTMuMTcsIGZ1bmN0aW9uKHgpIGFzLmxpc3QoYXMubnVtZXJpYyhzdHJzcGxpdCh4LCAiLCIpW1sxXV0pKSkNCiMgY291bnQgdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlcyBvZiBlYWNoIHZhbHVlDQpxM18xN19wcm9wIDwtIHEzXzE3X3RhYmxlICU+JQ0KICB1bm5lc3QoUTMuMTcpICU+JQ0KICBncm91cF9ieShncm91cCxgUTMuMTdgKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gJ2Ryb3AnKQ0KcTNfMTdfcHJvcCRRMy4xNyA8LSBhcy5udW1lcmljKHEzXzE3X3Byb3AkUTMuMTcpDQojIGNyZWF0ZSBhIGNvbnRpbmdlbmN5IHRhYmxlDQpxM18xN19jb250aW5nZW5jeSA8LSB4dGFicyhjb3VudCB+IGBRMy4xN2AgKyBncm91cCwgZGF0YSA9IHEzXzE3X3Byb3ApDQpwcmludChxM18xN19jb250aW5nZW5jeSkNCiMgQ2hpLXNxdWFyZWQgdGVzdA0KY2hpc3EudGVzdChxM18xN19jb250aW5nZW5jeSkNCmBgYA0KUGxvdCBzb3VyY2Ugb2YgaW5mbGF0aW9uIGZvcmVjYXN0cyBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgY29udmVydCBjb250aW5nZW5jeSB0YWJsZSB0byBkYXRhIGZyYW1lDQpxM18xN19wcm9wIDwtIGFzLmRhdGEuZnJhbWUocTNfMTdfY29udGluZ2VuY3kpICU+JQ0KICBsZWZ0X2pvaW4oZ3JvdXBfdG90YWwsIGJ5ID0gImdyb3VwIikgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gRnJlcSAvIG5fcmVzcG9uZGVudHMpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0KcTNfMTdfcHJvcCA8LSBxM18xN19wcm9wICU+JQ0KICBtdXRhdGUoUTMuMTdfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgYFEzLjE3YCA9PSAiMSIgfiAiMS1UZWxldmlzaW9uLCByYWRpbyBvciBwcmludCBtZWRpYSIsDQogICAgYFEzLjE3YCA9PSAiMiIgfiAiMi1Tb2NpYWwgbWVkaWEiLA0KICAgIGBRMy4xN2AgPT0gIjMiIH4gIjMtT2ZmaWNpYWwgd2Vic2l0ZXMgb3IgZGF0YSByZWxlYXNlcyIsDQogICAgYFEzLjE3YCA9PSAiNCIgfiAiNC1Db250ZW50IHBsYXRmb3JtIiwNCiAgICBgUTMuMTdgID09ICI1IiB+ICI1LUFjdGl2ZWx5IHNlYXJjaCBvbiBzZWFyY2ggZW5naW5lcyIsDQogICAgYFEzLjE3YCA9PSAiNiIgfiAiNi1GYW1pbHkgb3IgZnJpZW5kcyIsDQogICAgYFEzLjE3YCA9PSAiNyIgfiAiNy1GaW5hbmNpYWwgYWR2aWNlIHdlYnNpdGVzL2ZvcnVtcyIsDQogICAgYFEzLjE3YCA9PSAiOCIgfiAiOC1Qcml2YXRlIGJhbmtzIG9yIGVjb25vbWljIHJlc2VhcmNoIGluc3RpdHV0ZXMiLA0KICAgIGBRMy4xN2AgPT0gIjkiIH4gIjktT3RoZXIiDQogICkpDQpnZ3Bsb3QocTNfMTdfcHJvcCwgYWVzKHggPSBmYWN0b3IoYFEzLjE3X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gZ3JvdXApKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlEzLjE3IFNvdXJjZSBvZiBJbmZsYXRpb24gRm9yZWNhc3RzIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQpQbG90IHBlcmNlbnRhZ2UgYmFyIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnEzXzE3X3N1bW1hcnkgPC0gcTNfMTdfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoYFEzLjE3X2xhYmVsYCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShGcmVxKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lDQogIG11dGF0ZShwcm9wb3J0aW9uID0gdG90YWxfY291bnQgLyB0b3RhbF9yZXNwb25kZW50cykNCmdncGxvdChxM18xN19zdW1tYXJ5LCBhZXMoeCA9IGZhY3RvcihRMy4xN19sYWJlbCksIHkgPSBwcm9wb3J0aW9uKSkgKw0KICBnZW9tX2NvbChmaWxsID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChwcm9wb3J0aW9uICogMTAwLCAxKSwgIiUiKSksIA0KICAgICAgICAgICAgdmp1c3QgPSAtMC4zLCBzaXplID0gMy41KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQZXJjZW50YWdlIG9mIFBhcnRpY2lwYW50cyBTZWxlY3RpbmcgRWFjaCBRMy4xNyBPcHRpb24iLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUGVyY2VudGFnZSBvZiBQYXJ0aWNpcGFudHMiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNCiMjIFEzLjE4IEltcGFjdCBvZiBJbmZsYXRpb24gRm9yZWNhc3RzDQpUbyB3aGF0IGV4dGVudCBkbyB5b3UgZmVlbCB0aGF0IGluZmxhdGlvbiBmb3JlY2FzdHMgKGluZm9ybWF0aW9uIGFib3V0IGZ1dHVyZSBpbmZsYXRpb24pIGltcGFjdCB5b3VyIHBlcnNvbmFsIGZpbmFuY2VzP1wNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgKyBjaGktc3F1YXJlZCB0ZXN0XA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKg0KYGBge3J9DQojIEluaXRpYWwgQ2hlY2sNCnN1bW1hcnkoYXMubnVtZXJpYyhyYXdkYXRhX3ZhbHVlJFEzLjE4KSkNCnEzXzE4X3RhYmxlIDwtIHJhd2RhdGFfdmFsdWVbLCBjKCJRMy4xOCIsICJncm91cCIpXQ0KcTNfMThfY29udGluZ2VuY3kgPC0gdGFibGUocTNfMThfdGFibGUkUTMuMTgsIHEzXzE4X3RhYmxlJGdyb3VwKQ0KcHJpbnQocTNfMThfY29udGluZ2VuY3kpDQojIENoaS1zcXVhcmVkIHRlc3QNCmNoaXNxLnRlc3QocTNfMThfY29udGluZ2VuY3kpDQpgYGANCkltcGFjdCBvZiBJbmZsYXRpb24gRm9yZWNhc3RzIHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0KcTNfMThfcHJvcCAgPC0gYXMuZGF0YS5mcmFtZShxM18xOF9jb250aW5nZW5jeSkNCiMgcmVuYW1lIGNvbHVtbnMNCm5hbWVzKHEzXzE4X3Byb3ApIDwtIGMoIlEzLjE4IiwgIkdyb3VwIiwgIkNvdW50IikNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpxM18xOF9wcm9wIDwtIHEzXzE4X3Byb3AgJT4lDQogIG11dGF0ZShRMy4xOF9sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBRMy4xOCA9PSAiMSIgfiAiMS1Ob3QgYXQgYWxsIiwNCiAgICBRMy4xOCA9PSAiMiIgfiAiMi1TbGlnaHRseSIsDQogICAgUTMuMTggPT0gIjMiIH4gIjMtTW9kZXJhdGVseSIsDQogICAgUTMuMTggPT0gIjQiIH4gIjQtVmVyeSBzaWduaWZpY2FudGx5Ig0KICApKQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnEzXzE4X3Byb3AgPC0gcTNfMThfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoR3JvdXApICU+JQ0KICBtdXRhdGUoUHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkNCmdncGxvdChxM18xOF9wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUTMuMThfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUTMuMTggSW1wYWN0IG9mIEluZmxhdGlvbiBGb3JlY2FzdHMgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQpQbG90IHBpZSBjaGFydCBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQpxM18xOF9zdW1tYXJ5IDwtIHEzXzE4X3Byb3AgJT4lDQogIGdyb3VwX2J5KGBRMy4xOF9sYWJlbGApICU+JQ0KICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oQ291bnQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSB0b3RhbF9jb3VudCAvIHN1bSh0b3RhbF9jb3VudCksDQogICAgICAgICBgUTMuMThfbGFiZWxgID0gcGFzdGUwKGBRMy4xOF9sYWJlbGAsICIgKCIsIHJvdW5kKHByb3BvcnRpb24gKiAxMDAsIDIpLCAiICUpIikpDQpnZ3Bsb3QocTNfMThfc3VtbWFyeSwgYWVzKHggPSAiIix5ID0gcHJvcG9ydGlvbiwgZmlsbCA9IGBRMy4xOF9sYWJlbGApKSArDQogIGdlb21fY29sKHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICBsYWJzKHRpdGxlID0gIlEzLjE4IEltcGFjdCBvZiBJbmZsYXRpb24gRm9yZWNhc3RzIFN1bW1hcnkgUGllIENoYXJ0IiwNCiAgICAgICB4ID0gIiIsDQogICAgICAgeSA9ICIiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCiMjIFEzLjE5IFJlc3BvbnNlIHRvIEluZmxhdGlvbiBGb3JlY2FzdHMNCkhvdyBtdWNoIGRvIHlvdSBhZGp1c3Qgb3IgdGFrZSBhY3Rpb24gaW4gcmVzcG9uc2UgdG8gaW5mbGF0aW9uIGZvcmVjYXN0cyAoaW5mb3JtYXRpb24gYWJvdXQgZnV0dXJlIGluZmxhdGlvbik/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSArIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0Kc3VtbWFyeShhcy5udW1lcmljKHJhd2RhdGFfdmFsdWUkUTMuMTkpKQ0KcTNfMTlfdGFibGUgPC0gcmF3ZGF0YV92YWx1ZVssIGMoIlEzLjE5IiwgImdyb3VwIildDQpxM18xOV9jb250aW5nZW5jeSA8LSB0YWJsZShxM18xOV90YWJsZSRRMy4xOSwgcTNfMTlfdGFibGUkZ3JvdXApDQpwcmludChxM18xOV9jb250aW5nZW5jeSkNCiMgQ2hpLXNxdWFyZWQgdGVzdA0KY2hpc3EudGVzdChxM18xOV9jb250aW5nZW5jeSkNCmBgYA0KUmVzcG9uc2UgdG8gSW5mbGF0aW9uIEZvcmVjYXN0cyBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnEzXzE5X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUocTNfMTlfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhxM18xOV9wcm9wKSA8LSBjKCJRMy4xOSIsICJHcm91cCIsICJDb3VudCIpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0KcTNfMTlfcHJvcCA8LSBxM18xOV9wcm9wICU+JQ0KICBtdXRhdGUoUTMuMTlfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgUTMuMTkgPT0gIjEiIH4gIjEtTm90IGF0IGFsbCIsDQogICAgUTMuMTkgPT0gIjIiIH4gIjItUmFyZWx5IiwNCiAgICBRMy4xOSA9PSAiMyIgfiAiMy1Tb21ld2hhdCBhY3RpdmVseSIsDQogICAgUTMuMTkgPT0gIjQiIH4gIjQtVmVyeSBhY3RpdmVseSINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpxM18xOV9wcm9wIDwtIHEzXzE5X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3QocTNfMTlfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYFEzLjE5X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlEzLjE5IFJlc3BvbnNlIHRvIEluZmxhdGlvbiBGb3JlY2FzdHMgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KUGxvdCBwaWUgY2hhcnQgaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0KcTNfMTlfc3VtbWFyeSA8LSBxM18xOV9wcm9wICU+JQ0KICBncm91cF9ieShgUTMuMTlfbGFiZWxgKSAlPiUNCiAgc3VtbWFyaXNlKHRvdGFsX2NvdW50ID0gc3VtKENvdW50KSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lDQogIG11dGF0ZShwcm9wb3J0aW9uID0gdG90YWxfY291bnQgLyBzdW0odG90YWxfY291bnQpLA0KICAgICAgICAgYFEzLjE5X2dyYXBoX2xhYmVsYCA9IHBhc3RlMChgUTMuMTlfbGFiZWxgLCAiICgiLCByb3VuZChwcm9wb3J0aW9uICogMTAwLCAyKSwgIiAlKSIpKQ0KZ2dwbG90KHEzXzE5X3N1bW1hcnksIGFlcyh4ID0gIiIseSA9IHByb3BvcnRpb24sIGZpbGwgPSBgUTMuMTlfZ3JhcGhfbGFiZWxgKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgbGFicyh0aXRsZSA9ICJRMy4xOSBSZXNwb25zZSB0byBJbmZsYXRpb24gRm9yZWNhc3RzIFN1bW1hcnkgUGllIENoYXJ0IiwNCiAgICAgICB4ID0gIiIsDQogICAgICAgeSA9ICIiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCg0KDQoNCiMgQWN0dWFsIFN1cnZleSBBbmFseXNpcyA8YSBuYW1lPSJhY3R1YWwtc3VydmV5LWFuYWx5c2lzIj48L2E+DQoNCiMjICEgUXh4LjIgR3JhcGggRmFtaWxhcml0eQ0KSGF2ZSB5b3UgZXZlciBiZWVuIGNvbW11bmljYXRlZCB0aGlzIHR5cGUgb2YgaW5mb3JtYXRpb24gYmVmb3JlP1wNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogQ29udGluZ2VuY3kgVGFibGUgKyBDaGktc3F1YXJlZCB0ZXN0XA0KKnJlY29kZSB0byB5ZXMgYW5kIG5vKlwNCioqUmVzdWx0OiBXZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMsIG1lYW5pbmcgcGVvcGxlIGFyZSBtb3JlIG9yIGxlc3MgZmFtaWxpYXIgd2l0aCBjZXJ0YWluIHR5cGUgb2YgdmlzdWFsaXNhdGlvbnMuKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfcTIgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTJfbGlzdCA8LSBsaXN0KCJRNC4yIiwiUTYuMiIsICJROC4yIiwgIlExMC4yIiwgIlExMi4yIikNCg0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9xMl9saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygicTJfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTIgPC0gcmJpbmQoc3VydmV5X3EyLCB0ZW1wX3RhYmxlKQ0KfQ0KDQojIHJlY29kZSB0aGUgY2F0ZWdvcnkNCnN1cnZleV9xMiA8LSBzdXJ2ZXlfcTIgJT4lDQogIG11dGF0ZShxMl9yZWNvZGUgPSBjYXNlX3doZW4oDQogICAgcTJfdmFsdWUgJWluJSBjKCIxIiwgIjIiKSB+ICJOIiwNCiAgICBxMl92YWx1ZSAlaW4lIGMoIjMiLCAiNCIpIH4gIlkiDQogICkpDQoNCnN1cnZleV9xMl9jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfcTIkcTJfcmVjb2RlLCBzdXJ2ZXlfcTIkZ3JvdXApDQojIHByaW50IHRoZSBjb250aW5nZW5jeSB0YWJsZQ0KcHJpbnQoc3VydmV5X3EyX2NvbnRpbmdlbmN5KQ0KIyBDaGktc3F1YXJlZCB0ZXN0DQpjaGlzcS50ZXN0KHN1cnZleV9xMl9jb250aW5nZW5jeSkNCg0KIyBjaGlzcV9yZXN1bHQgPC0gY2hpc3EudGVzdChzdXJ2ZXlfcTJfY29udGluZ2VuY3kpDQojIGNoaXNxX3Jlc3VsdCRzdGRyZXMgIA0KIyBjaGlzcV9yZXN1bHQkZXhwZWN0ZWQgIyhJZiBtYW55IHZhbHVlcyBhcmUgPCA1LCB5b3VyIENoaS1zcXVhcmVkIHRlc3QgbWF5IGJlIGxlc3MgcmVsaWFibGUuKQ0KIyBQb3N0LWhvYyB0ZXN0IGZvciBOIC0tPiBubyBzaW5nbGUgcGFpcndpc2UgZGlmZmVyZW5jZSBpcyBzdHJvbmcNCiMgcGFpcndpc2UucHJvcC50ZXN0KA0KIyAgIHggPSBzdXJ2ZXlfcTJfY29udGluZ2VuY3lbIk4iLCBdLA0KIyAgIG4gPSBjb2xTdW1zKHN1cnZleV9xMl9jb250aW5nZW5jeSksDQojICAgcC5hZGp1c3QubWV0aG9kID0gImhvbG0iDQojICkNCg0KYGBgDQoNClN1bW1hcnkgVGFibGUgb2YgcHJvcG9ydGlvbiBvZiB5ZXMgYW5kIG5vDQoNCmBgYHtyfQ0KeWVzX3BlciA8LSBzdXJ2ZXlfcTJfY29udGluZ2VuY3lbMixdDQpub19wZXIgPC0gc3VydmV5X3EyX2NvbnRpbmdlbmN5WzEsXQ0KZmFtaWxhcml0eV9ncm91cF90b3RhbCA8LSBjb2xTdW1zKHN1cnZleV9xMl9jb250aW5nZW5jeSkNCnllc19wcm9wIDwtIHllc19wZXIvZmFtaWxhcml0eV9ncm91cF90b3RhbA0Kbm9fcHJvcCA8LSBub19wZXIvZmFtaWxhcml0eV9ncm91cF90b3RhbA0KIyBjb252ZXJ0IHRvIGRhdGEgZnJhbWUNCnN1cnZleV9xMl9zdW1tYXJ5IDwtZGF0YS5mcmFtZSh5ZXNfcHJvcCwgbm9fcHJvcCkNCg0KYGBgDQoNClBsb3QgdGhlIGdyYXBoDQoNCmBgYHtyfQ0KZ2dwbG90KHN1cnZleV9xMiwgYWVzKHggPSBxMl9yZWNvZGUsIGZpbGwgPSBncm91cCkpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnModGl0bGUgPSAiSGF2ZSB5b3UgZXZlciBiZWVuIGNvbW11bmljYXRlZCB0aGlzIHR5cGUgb2YgaW5mb3JtYXRpb24gYmVmb3JlPyIsDQogICAgICAgeCA9ICJSZXNwb25zZSIsDQogICAgICAgeSA9ICJDb3VudCIpICsNCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojIyBReHguMyBQcmlvciBFeHBlY3RhdGlvbg0KRG9lcyB0aGUgaW5mbGF0aW9uIGZvcmVjYXN0IGluZm9ybWF0aW9uIHByb3ZpZGVkIGFsaWduIHdpdGggeW91ciBleHBlY3RhdGlvbnM/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBDb250aW5nZW5jeSBUYWJsZSArIENoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyoqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3EzIDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X3EzX2xpc3QgPC0gbGlzdCgiUTQuMyIsIlE2LjMiLCAiUTguMyIsICJRMTAuMyIsICJRMTIuMyIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3EzX2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxM192YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xMyA8LSByYmluZChzdXJ2ZXlfcTMsIHRlbXBfdGFibGUpDQp9DQoNCiMgSW5pdGlhbCBDaGVjaw0Kc3VtbWFyeShhcy5udW1lcmljKHN1cnZleV9xMyRxM192YWx1ZSkpDQpgYGANClRlc3QgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gZ3JvdXBzDQpgYGB7cn0NCnN1cnZleV9xM19jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfcTMkcTNfdmFsdWUsIHN1cnZleV9xMyRncm91cCkNCiMgcHJpbnQgdGhlIGNvbnRpbmdlbmN5IHRhYmxlDQpwcmludChzdXJ2ZXlfcTNfY29udGluZ2VuY3kpDQojIENoaS1zcXVhcmVkIHRlc3QNCmNoaXNxLnRlc3Qoc3VydmV5X3EzX2NvbnRpbmdlbmN5KQ0KYGBgDQpQbG90IHByaW9yIGV4cGVjdGF0aW9uIHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0Kc3VydmV5X3EzX3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUoc3VydmV5X3EzX2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMoc3VydmV5X3EzX3Byb3ApIDwtIGMoIlEzLjMiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnN1cnZleV9xM19wcm9wIDwtIHN1cnZleV9xM19wcm9wICU+JQ0KICBtdXRhdGUoUTMuM19sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBRMy4zID09ICIxIiB+ICIxLVN0cm9uZ2x5IGFsaWducyIsDQogICAgUTMuMyA9PSAiMiIgfiAiMi1Tb21ld2hhdCBhbGlnbnMiLA0KICAgIFEzLjMgPT0gIjMiIH4gIjMtTmV1dHJhbCIsDQogICAgUTMuMyA9PSAiNCIgfiAiNC1Tb21ld2hhdCBkb2VzIG5vdCBhbGlnbiIsDQogICAgUTMuMyA9PSAiNSIgfiAiNS1Eb2VzIG5vdCBhbGlnbiBhdCBhbGwiLA0KICApKQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnN1cnZleV9xM19wcm9wIDwtIHN1cnZleV9xM19wcm9wICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gQ291bnQgLyBzdW0oQ291bnQpKQ0KZ2dwbG90KHN1cnZleV9xM19wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUTMuM19sYWJlbGApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IEdyb3VwKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJRMy4zIFByaW9yIEV4cGVjdGF0aW9uIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgcGllIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnN1cnZleV9xM19zdW1tYXJ5IDwtIHN1cnZleV9xM19wcm9wICU+JQ0KICBncm91cF9ieShgUTMuM19sYWJlbGApICU+JQ0KICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oQ291bnQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSB0b3RhbF9jb3VudCAvIHN1bSh0b3RhbF9jb3VudCksDQogICAgICAgICBgUTMuM19ncmFwaF9sYWJlbGAgPSBwYXN0ZTAoYFEzLjNfbGFiZWxgLCAiICgiLCByb3VuZChwcm9wb3J0aW9uICogMTAwLCAyKSwgIiAlKSIpKQ0KZ2dwbG90KHN1cnZleV9xM19zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gYFEzLjNfZ3JhcGhfbGFiZWxgKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgbGFicyh0aXRsZSA9ICJRMy4zIFByaW9yIEV4cGVjdGF0aW9uIFN1bW1hcnkgUGllIENoYXJ0IiwNCiAgICAgICB4ID0gIiIsDQogICAgICAgeSA9ICIiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQojIyBReHguNCBDb25mbGljdGlvbiB3aXRoIFByaW9yIEV4cGVjdGF0aW9uDQpIb3cgZG9lcyB0aGUgaW5mbGF0aW9uIGZvcmVjYXN0IGNvbmZsaWN0IHdpdGggeW91ciBleHBlY3RhdGlvbnM/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjYWxjdWxhdGUgdG90YWwgbnVtYmVyIG9mIHBlb3BsZSB3aG8gdGhpbmsgdGhlIGZvcmVjYXN0IGlzIG5vdCBhbGlnbmVkIHdpdGggdGhlaXIgZXhwZWN0YXRpb25cDQoqKlJlc3VsdDogQW1vbmcgcGVvcGxlIHdobyB0aGluayB0aGUgZm9yZWNhc3QgaXMgbm90IGFsaWduZWQgd2l0aCB0aGVpciBleHBlY3RhdGlvbiwgOTAlIHBlcmNlbnQgb2YgcmVzcG9uZGVudHMgdGhpbmtzIHRoZSBmb3JlY2FzdCBpcyBsb3dlciB0aGFuIHdoYXQgdGhleSBleHBlY3RlZC4qKg0KYGBge3J9DQojIENoZWNrIHRoZSBudW1iZXIgb2YgcGVvcGxlIGFuc3dlcmVkIHRoaXMgcXVlc3Rpb24NCm5fbm90X2FsaWduIDwtIHN1bShzdXJ2ZXlfcTNfc3VtbWFyeSR0b3RhbF9jb3VudFs0OjVdKQ0KIyBDb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfcTQgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTRfbGlzdCA8LSBsaXN0KCJRNC40IiwiUTYuNCIsICJROC40IiwgIlExMC40IiwgIlExMi40IikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTRfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoInE0X3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X3E0IDwtIHJiaW5kKHN1cnZleV9xNCwgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9xNCA8LSBzdXJ2ZXlfcTRbIWlzLm5hKHN1cnZleV9xNCRxNF92YWx1ZSksIF0NCnN1cnZleV9xNF9jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfcTQkcTRfdmFsdWUsIHN1cnZleV9xNCRncm91cCkNCiMgcHJpbnQgdGhlIGNvbnRpbmdlbmN5IHRhYmxlDQpwcmludChzdXJ2ZXlfcTRfY29udGluZ2VuY3kpDQoNCmBgYA0KUGxvdCBjb25mbGljdGlvbiB3aXRoIHByaW9yIGV4cGVjdGF0aW9uIHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0Kc3VydmV5X3E0X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUoc3VydmV5X3E0X2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMoc3VydmV5X3E0X3Byb3ApIDwtIGMoIlE0LjQiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnN1cnZleV9xNF9wcm9wIDwtIHN1cnZleV9xNF9wcm9wICU+JQ0KICBtdXRhdGUoUTQuNF9sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBRNC40ID09ICIxIiB+ICIxLUhpZ2hlciB0aGFuIHdoYXQgSSBleHBlY3RlZCIsDQogICAgUTQuNCA9PSAiMiIgfiAiMi1Mb3dlciB0aGFuIHdoYXQgSSBleHBlY3RlZCINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpzdXJ2ZXlfcTRfcHJvcCA8LSBzdXJ2ZXlfcTRfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoR3JvdXApICU+JQ0KICBtdXRhdGUoUHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkNCmdncGxvdChzdXJ2ZXlfcTRfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYFE0LjRfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUTQuNCBDb25mbGljdGlvbiB3aXRoIFByaW9yIEV4cGVjdGF0aW9uIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgcGllIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnN1cnZleV9xNF9zdW1tYXJ5IDwtIHN1cnZleV9xNF9wcm9wICU+JQ0KICBncm91cF9ieShgUTQuNF9sYWJlbGApICU+JQ0KICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oQ291bnQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSB0b3RhbF9jb3VudCAvIHN1bSh0b3RhbF9jb3VudCksDQogICAgICAgICBgUTQuNF9ncmFwaF9sYWJlbGAgPSBwYXN0ZTAoYFE0LjRfbGFiZWxgLCAiICgiLCByb3VuZChwcm9wb3J0aW9uICogMTAwLCAyKSwgIiAlKSIpKQ0KZ2dwbG90KHN1cnZleV9xNF9zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gYFE0LjRfZ3JhcGhfbGFiZWxgKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgbGFicyh0aXRsZSA9ICJRNC40IENvbmZsaWN0aW9uIHdpdGggUHJpb3IgRXhwZWN0YXRpb24gU3VtbWFyeSBQaWUgQ2hhcnQiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCiMjIFF4eC42IFByb2JhYmlsaXR5IG9mIGV4YWN0bHkgMi42JQ0Kd2hhdCBkbyB5b3UgdGhpbmsgaXMgdGhlIHByb2JhYmlsaXR5IG9mIGluZmxhdGlvbiBiZWluZyBleGFjdGx5IDIuNiU/XA0KRGVmaW5pdGl2ZSBDb3JyZWN0IEFuc3dlclwNCipkZXNjZW5kaW5nIG9yZGVyKlwNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgJiBwcm9wb3J0aW9uIHRlc3RcDQoqKlJlc3VsdDogVGhlcmUgaXMgbm8gc3RhdGlzdGljYWwgZGlmZmVyZW5jZSBpbiB0ZXJtcyBvZiBjb3JyZWN0bHkgYW5zd2VyaW5nIHRoZSBwcm9iYWJpbGl0eSBvZiBpbmZsYXRpb24gYmVpbmcgZXhhY3RseSAyLjYlLioqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3E2IDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X3E2X2xpc3QgPC0gbGlzdCgiUTQuNiIsIlE2LjYiLCAiUTguNiIsICJRMTAuNiIsICJRMTIuNiIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3E2X2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxNl92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xNiA8LSByYmluZChzdXJ2ZXlfcTYsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTYkcTZfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfcTYkcTZfdmFsdWUpDQoNCnN1cnZleV9xNl9jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfcTYkcTZfdmFsdWUsIHN1cnZleV9xNiRncm91cCkNCnByaW50KHN1cnZleV9xNl9jb250aW5nZW5jeSkNCg0KDQojIHdoZXRoZXIgb25lIHByb3BvcnRpb24gZGlmZmVycyBhY3Jvc3MgZ3JvdXBzDQpsZXNzX3RoYW5fMV9wZXIgPC0gc3VydmV5X3E2X2NvbnRpbmdlbmN5WzcsXQ0Kc3VydmV5X3E2X2dyb3VwX3RvdGFsIDwtIGNvbFN1bXMoc3VydmV5X3E2X2NvbnRpbmdlbmN5KQ0KcHJvcC50ZXN0KGxlc3NfdGhhbl8xX3Blciwgc3VydmV5X3E2X2dyb3VwX3RvdGFsKQ0KDQpgYGANClBsb3QgcHJvYmFiaWxpdHkgb2YgZXhhY3RseSAyLjYlIHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0Kc3VydmV5X3E2X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUoc3VydmV5X3E2X2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMoc3VydmV5X3E2X3Byb3ApIDwtIGMoIlF4eC42IiwgIkdyb3VwIiwgIkNvdW50IikNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpzdXJ2ZXlfcTZfcHJvcCA8LSBzdXJ2ZXlfcTZfcHJvcCAlPiUNCiAgbXV0YXRlKFF4eC42X2xhYmVsID0gY2FzZV93aGVuKA0KICAgIFF4eC42ID09ICIxIiB+ICIxLT45OSUiLA0KICAgIFF4eC42ID09ICIyIiB+ICIyLWFyb3VuZCA4MCUiLA0KICAgIFF4eC42ID09ICIzIiB+ICIzLWFyb3VuZCA2MCUiLA0KICAgIFF4eC42ID09ICI0IiB+ICI0LWFyb3VuZCA1MCUiLA0KICAgIFF4eC42ID09ICI1IiB+ICI1LWFyb3VuZCAzMCUiLA0KICAgIFF4eC42ID09ICI2IiB+ICI2LWFyb3VuZCAyMCUiLA0KICAgIFF4eC42ID09ICI3IiB+ICI3LTwxJSINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpzdXJ2ZXlfcTZfcHJvcCA8LSBzdXJ2ZXlfcTZfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoR3JvdXApICU+JQ0KICBtdXRhdGUoUHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkNCmdncGxvdChzdXJ2ZXlfcTZfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYFF4eC42X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofkdyb3VwKSsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguNiBQcm9iYWJpbGl0eSBvZiBleGFjdGx5IDIuNiUgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KUGxvdCB0aGUgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X3E2LCBhZXMoeCA9IHE2X3ZhbHVlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogIGxhYnModGl0bGUgPSAiUXh4LjYgUHJvYmFiaWxpdHkgb2YgZXhhY3RseSAyLjYlIEhpc3RvZ3JhbSIsDQogICAgICAgeCA9ICJSZXNwb25zZSIsDQogICAgICAgeSA9ICJDb3VudCIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCBtYXgoc3VydmV5X3E2JHE2X3ZhbHVlLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KUGxvdCBwaWUgY2hhcnQgaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0Kc3VydmV5X3E2X3N1bW1hcnkgPC0gc3VydmV5X3E2X3Byb3AgJT4lDQogIGdyb3VwX2J5KGBRNi42X2xhYmVsYCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShDb3VudCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBtdXRhdGUocHJvcG9ydGlvbiA9IHRvdGFsX2NvdW50IC8gc3VtKHRvdGFsX2NvdW50KSwNCiAgICAgICAgIGBRNi42X2dyYXBoX2xhYmVsYCA9IHBhc3RlMChgUTYuNl9sYWJlbGAsICIgKCIsIHJvdW5kKHByb3BvcnRpb24gKiAxMDAsIDIpLCAiICUpIikpDQpnZ3Bsb3Qoc3VydmV5X3E2X3N1bW1hcnksIGFlcyh4ID0gIiIseSA9IHByb3BvcnRpb24sIGZpbGwgPSBgUTYuNl9ncmFwaF9sYWJlbGApKSArDQogIGdlb21fY29sKHdpZHRoID0gMSkgKw0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICBsYWJzKHRpdGxlID0gIlF4eC42IFByb2JhYmlsaXR5IG9mIGV4YWN0bHkgMi42JSBTdW1tYXJ5IFBpZSBDaGFydCIsDQogICAgICAgeCA9ICIiLA0KICAgICAgIHkgPSAiIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkNCmBgYA0KDQojIyAhIFF4eC43IFByb2JhYmlsaXR5IG9mIGJldHdlZW4gMS45JSBhbmQgMy4zJQ0Kd2hhdCBkbyB5b3UgdGhpbmsgaXMgdGhlIHByb2JhYmlsaXR5IG9mIGluZmxhdGlvbiBiZWluZyBiZXR3ZWVuIDEuOSUgYW5kIDMuMyU/XA0KRGVmaW5pdGl2ZSBDb3JyZWN0IEFuc3dlclwNCipkZXNjZW5kaW5nIG9yZGVyKlwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgJiBwcm9wb3J0aW9uIHRlc3RcDQoqKlJlc3VsdDogVGhlcmUgaXMgc3RhdGlzdGljYWwgZGlmZmVyZW5jZSBpbiBjb250cm9sIGdyb3VwIGluIHRlcm1zIG9mIHRoZSBwcm9wb3J0aW9uIG9mIHRoZSBjb3JyZWN0IGFuc3dlciBvZiBob3cgcGVvcGxlIHRoaW5rIHRoZSBwcm9iYWJpbGl0eSBvZiBpbmZsYXRpb24gYmVpbmcgYmV0d2VlbiAxLjklIGFuZCAzLjMlIGlzLiAqKlwNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfcTcgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTdfbGlzdCA8LSBsaXN0KCJRNC43IiwiUTYuNyIsICJROC43IiwgIlExMC43IiwgIlExMi43IikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTdfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoInE3X3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X3E3IDwtIHJiaW5kKHN1cnZleV9xNywgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9xNyRxN192YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xNyRxN192YWx1ZSkNCmBgYA0KDQpUZXN0IHRoZSBwcm9wb3J0aW9uIG9mIGNvcnJlY3QgYW5zd2VyDQpgYGB7cn0NCnN1cnZleV9xN19jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfcTckcTdfdmFsdWUsIHN1cnZleV9xNyRncm91cCkNCiMgcHJpbnQgdGhlIGNvbnRpbmdlbmN5IHRhYmxlDQpwcmludChzdXJ2ZXlfcTdfY29udGluZ2VuY3kpDQojIGNvcnJlY3QgYW5zd2VyDQpzdXJ2ZXlfcTdfY29ycmVjdCA8LSBzdXJ2ZXlfcTdfY29udGluZ2VuY3lbNSxdDQpzdXJ2ZXlfcTdfZ3JvdXBfdG90YWwgPC0gY29sU3VtcyhzdXJ2ZXlfcTdfY29udGluZ2VuY3kpDQpwcm9wLnRlc3Qoc3VydmV5X3E3X2NvcnJlY3QsIHN1cnZleV9xN19ncm91cF90b3RhbCkNCiMgcGFpcndpc2UgcHJvcG9ydGlvbiB0ZXN0DQpwYWlyd2lzZS5wcm9wLnRlc3QoDQogIHggPSBzdXJ2ZXlfcTdfY29udGluZ2VuY3lbNSwgXSwNCiAgbiA9IGNvbFN1bXMoc3VydmV5X3E3X2NvbnRpbmdlbmN5KSwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiICMgb3IgImhvbG0iLCAiQkgiDQopDQpgYGANCg0KDQpQbG90IHByb2JhYmlsaXR5IG9mIGJldHdlZW4gMS45JSBhbmQgMy4zJSBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnN1cnZleV9xN19wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHN1cnZleV9xN19jb250aW5nZW5jeSkNCiMgcmVuYW1lIGNvbHVtbnMNCm5hbWVzKHN1cnZleV9xN19wcm9wKSA8LSBjKCJReHguNyIsICJHcm91cCIsICJDb3VudCIpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0Kc3VydmV5X3E3X3Byb3AgPC0gc3VydmV5X3E3X3Byb3AgJT4lDQogIG11dGF0ZShReHguN19sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBReHguNyA9PSAiMSIgfiAiMS0+OTklIiwNCiAgICBReHguNyA9PSAiMiIgfiAiMi1hcm91bmQgODAlIiwNCiAgICBReHguNyA9PSAiMyIgfiAiMy1hcm91bmQgNjAlIiwNCiAgICBReHguNyA9PSAiNCIgfiAiNC1hcm91bmQgNTAlIiwNCiAgICBReHguNyA9PSAiNSIgfiAiNS1hcm91bmQgMzAlIiwNCiAgICBReHguNyA9PSAiNiIgfiAiNi1hcm91bmQgMjAlIiwNCiAgICBReHguNyA9PSAiNyIgfiAiNy08MSUiDQogICkpDQojIGNhbGN1bGF0ZSBwcm9wb3J0aW9ucyB3aXRoaW4gZWFjaCBncm91cA0Kc3VydmV5X3E3X3Byb3AgPC0gc3VydmV5X3E3X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3Qoc3VydmV5X3E3X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBReHguN19sYWJlbGApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IEdyb3VwKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH5Hcm91cCkrDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUXh4LjcgUHJvYmFiaWxpdHkgb2YgYmV0d2VlbiAxLjklIGFuZCAzLjMlIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgdGhlIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQojIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KZ2dwbG90KHN1cnZleV9xNywgYWVzKHggPSBxN192YWx1ZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICBsYWJzKHRpdGxlID0gIlF4eC43IFByb2JhYmlsaXR5IG9mIGJldHdlZW4gMS45JSBhbmQgMy4zJSBIaXN0b2dyYW0iLA0KICAgICAgIHggPSAiUXh4LjciLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHN1cnZleV9xNyRxN192YWx1ZSwgbmEucm0gPSBUUlVFKSwgYnkgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCiMjIFF4eC44IFByb2JhYmlsaXR5IG9mIGJldHdlZW4gMy4zJSBhbmQgNS42JQ0Kd2hhdCBkbyB5b3UgdGhpbmsgaXMgdGhlIHByb2JhYmlsaXR5IG9mIGluZmxhdGlvbiBiZWluZyBiZXR3ZWVuIDMuMyUgYW5kIDUuNiU/XA0KRGVmaW5pdGl2ZSBDb3JyZWN0IEFuc3dlclwNCipkZXNjZW5kaW5nIG9yZGVyKlwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgJiBwcm9wb3J0aW9uIHRlc3RcDQoqKlJlc3VsdDogVGhlIGNvbnRyb2wgZ3JvdXAgYW5kIHRoZSBlcnJvciBiYXIgZ3JvdXAgaGFzIHNob3duIHN0YXRpc3RpY2FsIGRpZmZlcmVuY2UuKipcDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3E4IDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X3E4X2xpc3QgPC0gbGlzdCgiUTQuOCIsIlE2LjgiLCAiUTguOCIsICJRMTAuOCIsICJRMTIuOCIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3E4X2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxOF92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xOCA8LSByYmluZChzdXJ2ZXlfcTgsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTgkcThfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfcTgkcThfdmFsdWUpDQoNCmBgYA0KDQpjb250aW5nZW5jeSB0YWJsZQ0KYGBge3J9DQpzdXJ2ZXlfcThfY29udGluZ2VuY3kgPC0gdGFibGUoc3VydmV5X3E4JHE4X3ZhbHVlLCBzdXJ2ZXlfcTgkZ3JvdXApDQojIHByaW50IHRoZSBjb250aW5nZW5jeSB0YWJsZQ0KcHJpbnQoc3VydmV5X3E4X2NvbnRpbmdlbmN5KQ0KIyBjb3JyZWN0IGFuc3dlcg0Kc3VydmV5X3E4X2NvcnJlY3QgPC0gc3VydmV5X3E4X2NvbnRpbmdlbmN5WzUsXQ0Kc3VydmV5X3E4X2dyb3VwX3RvdGFsIDwtIGNvbFN1bXMoc3VydmV5X3E4X2NvbnRpbmdlbmN5KQ0KcHJvcC50ZXN0KHN1cnZleV9xOF9jb3JyZWN0LCBzdXJ2ZXlfcThfZ3JvdXBfdG90YWwpDQojIHBhaXJ3aXNlIHByb3BvcnRpb24gdGVzdA0KcGFpcndpc2UucHJvcC50ZXN0KA0KICB4ID0gc3VydmV5X3E4X2NvbnRpbmdlbmN5WzUsIF0sDQogIG4gPSBjb2xTdW1zKHN1cnZleV9xOF9jb250aW5nZW5jeSksDQogIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiAjIG9yICJob2xtIiwgIkJIIg0KKQ0KDQoNCmBgYA0KUGxvdCBwcm9iYWJpbGl0eSBvZiBiZXR3ZWVuIDMuMyUgYW5kIDUuNiUgcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQpzdXJ2ZXlfcThfcHJvcCAgPC0gYXMuZGF0YS5mcmFtZShzdXJ2ZXlfcThfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhzdXJ2ZXlfcThfcHJvcCkgPC0gYygiUXh4LjgiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnN1cnZleV9xOF9wcm9wIDwtIHN1cnZleV9xOF9wcm9wICU+JQ0KICBtdXRhdGUoUXh4LjhfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgUXh4LjggPT0gIjEiIH4gIjEtPjk5JSIsDQogICAgUXh4LjggPT0gIjIiIH4gIjItYXJvdW5kIDgwJSIsDQogICAgUXh4LjggPT0gIjMiIH4gIjMtYXJvdW5kIDYwJSIsDQogICAgUXh4LjggPT0gIjQiIH4gIjQtYXJvdW5kIDUwJSIsDQogICAgUXh4LjggPT0gIjUiIH4gIjUtYXJvdW5kIDMwJSIsDQogICAgUXh4LjggPT0gIjYiIH4gIjYtYXJvdW5kIDIwJSIsDQogICAgUXh4LjggPT0gIjciIH4gIjctPDElIg0KICApKQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnN1cnZleV9xOF9wcm9wIDwtIHN1cnZleV9xOF9wcm9wICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gQ291bnQgLyBzdW0oQ291bnQpKQ0KZ2dwbG90KHN1cnZleV9xOF9wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUXh4LjhfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+R3JvdXApKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlF4eC44IFByb2JhYmlsaXR5IG9mIGJldHdlZW4gMy4zJSBhbmQgNS42JSBQcm9wb3Rpb24gUGxvdCBhY3Jvc3MgR3JvdXBzIiwNCiAgICB4ID0gIlJlc3BvbnNlIiwNCiAgICB5ID0gIlByb3BvcnRpb24iDQogICkgKw0KICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQpQbG90IHRoZSBoaXN0b2dyYW0gaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0KIyBoaXN0b2dyYW0gaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmdncGxvdChzdXJ2ZXlfcTgsIGFlcyh4ID0gcThfdmFsdWUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicyh0aXRsZSA9ICJReHguOCBQcm9iYWJpbGl0eSBvZiBiZXR3ZWVuIDMuMyUgYW5kIDUuNiUgSGlzdG9ncmFtIiwNCiAgICAgICB4ID0gIlF4eC44IiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIG1heChzdXJ2ZXlfcTgkcThfdmFsdWUsIG5hLnJtID0gVFJVRSksIGJ5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCiMjICEgUXh4LjEwIFByb2JhYmlsaXR5IG9mIGVuZGluZyBvdXRzaWRlIHRoZSByYW5nZQ0KQmFzZWQgb24gdGhlIGluZmxhdGlvbiBmb3JlY2FzdCBwcm92aWRlZCwgd2hhdCBkbyB5b3UgdGhpbmsgaXMgdGhlIHByb2JhYmlsaXR5IG9mIGluZmxhdGlvbiBlbmRpbmcgdXAgb3V0c2lkZSBvZiAgdGhlIHJhbmdlIGZyb20gLTAuNCUgdG8gNS42JT9cDQpEZWZpbml0aXZlIENvcnJlY3QgQW5zd2VyICh2YXJpZWQgYmV0d2VlbiBncm91cClcDQoqZGVzY2VuZGluZyBvcmRlcipcDQpWYXJpYWJsZTogY2F0ZWdvcmljYWxcDQpNZXRob2Q6IGNhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBmb3IgZWFjaCBncm91cCArIHByb3BvcnRpb24gdGVzdFwNCioqUmVzdWx0OiBDb250cm9sIGdyb3VwIHBlcmZvcm0gc2lnbmlmaWNhbnQgd29yc2UgdGhhbiBvdGhlciBncm91cHMuKipcDQpgYGB7cn0NCnN1cnZleV9xMTAgPC0gZGF0YS5mcmFtZSgNCiAgZ3JvdXAgICA9IGNoYXJhY3RlcigwKSwNCiAgY29ycmVjdCA9IGludGVnZXIoMCksDQogIHRvdGFsICAgPSBpbnRlZ2VyKDApLA0KICBwcm9wICAgID0gbnVtZXJpYygwKQ0KKQ0Kc3VydmV5X3ExMF9saXN0IDwtIGxpc3QoIlE0LjEwIiwiUTYuMTAiLCAiUTguMTAiLCAiUTEwLjEwIiwgIlExMi4xMCIpDQpzdXJ2ZXlfcTEwX2NvcnJlY3QgPC1jKDgsMTIsMTQsMTQsMTQpICMgMTAlLCA0MCUuIDEwJSwgMTAlLCAxMCUNCg0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9xMTBfbGlzdFtbaV1dDQogIHExMF9jb3JyZWN0IDwtIHN1cnZleV9xMTBfY29ycmVjdFtpXQ0KICANCiAgIyBjb3VudCB0b3RhbCBudW1iZXIgb2YgcGVvcGxlIGluIGVhY2ggZ3JvdXANCiAgdG90YWxfY291bnQgPC0gbnJvdyhkZikNCiAgIyBjb3VudCBudW1iZXIgb2YgcGVvcGxlIHdobyBhbnN3ZXJlZCBjb3JyZWN0bHkNCiAgY29ycmVjdF9jb3VudCA8LSBzdW0oZGZbLCBjb2xdID09IHExMF9jb3JyZWN0LCBuYS5ybSA9IFRSVUUpDQogICMgY29tcHV0ZSB0aGUgcHJvcG9ydGlvbg0KICBwcm9wIDwtIGNvcnJlY3RfY291bnQgLyB0b3RhbF9jb3VudA0KICAjIGNhcHR1cmUgdGhlIGdyb3VwIG5hbWUNCiAgZ3JwX2xhYmVsIDwtIG5hbWVzKGdyb3VwX2xpc3RbaV0pICANCiAgIyByb3ctYmluZCBpbnRvIHN1cnZleV9xMTANCiAgc3VydmV5X3ExMCA8LSByYmluZChzdXJ2ZXlfcTEwLCBkYXRhLmZyYW1lKA0KICAgIGdyb3VwID0gZ3JwX2xhYmVsLA0KICAgIGNvcnJlY3QgPSBjb3JyZWN0X2NvdW50LA0KICAgIHRvdGFsID0gdG90YWxfY291bnQsDQogICAgcHJvcCA9IHByb3ApKQ0KfQ0KDQojIHByb3BvcnRpb24gdGVzdCAtLT4gVGhlcmUgaXMgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZQ0KcHJvcC50ZXN0KHggPSBzdXJ2ZXlfcTEwJGNvcnJlY3QsDQogICAgICAgICAgbiA9IHN1cnZleV9xMTAkdG90YWwpDQojIHBhaXJ3aXNlIHByb3BvcnRpb24gdGVzdA0KcGFpcndpc2UucHJvcC50ZXN0KA0KICB4ID0gc2V0TmFtZXMoc3VydmV5X3ExMCRjb3JyZWN0LCBzdXJ2ZXlfcTEwJGdyb3VwKSwNCiAgbiA9IHNldE5hbWVzKHN1cnZleV9xMTAkdG90YWwsICAgc3VydmV5X3ExMCRncm91cCksDQogIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiAjIG9yICJob2xtIiwgIkJIIg0KKQ0KYGBgDQoNCmBgYHtyfQ0KDQpnZ3Bsb3Qoc3VydmV5X3ExMCwgYWVzKHggPSBncm91cCwgeSA9IHByb3ApKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNjYWxlczo6cGVyY2VudChwcm9wLCBhY2N1cmFjeSA9IDEpKSwgdmp1c3QgPSAtMC41KSArDQogIGxhYnModGl0bGUgPSAiUXh4LjEwIFByb2JhYmlsaXR5IG9mIGVuZGluZyBvdXRzaWRlIHRoZSByYW5nZSBjb3JyZWN0IGFuc3dlciByYXRlIiwNCiAgICAgICB4ID0gIkdyb3VwIiwNCiAgICAgICB5ID0gIlByb3BvcnRpb24iKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANClBsb3QgZGlzdHJpYnV0aW9uIGZvciBlYWNoIGluZGl2aWR1YWwgZ3JvdXANCmBgYHtyfQ0KZ2dwbG90KGNvbnRyb2xsZWRfZ3JvdXAsIGFlcyh4ID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoUTQuMTApKSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbGltaXRzID0gYygwLCA1MCksICAgICAgICAjIGZvcmNlIHkgZnJvbSAwIHVwIHRvIDYwDQogICAgYnJlYWtzID0gc2VxKDAsIDUwLCBieT0xMCkgIyB0aWNrcyBhdCAwLCAxMCwgMjAsIOKApiwgNjANCiAgKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSAuLmNvdW50Li4pLCBzdGF0ID0gImNvdW50Iiwgdmp1c3QgPSAtMC41KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29udHJvbGxlZCBHcm91cDogRGlzdHJpYnV0aW9uIG9mIFE0LjEwIFJlc3BvbnNlcyIsDQogICAgeCAgICAgPSAiUTQuMTAgKG51bWVyaWMpIiwNCiAgICB5ICAgICA9ICJDb3VudCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQojIyBReHguMTEgUHJvYmFiaWxpdHkgb2YgaGlnaGVyIHRoYW4gNiUNCkJhc2VkIG9uIHRoZSBpbmZsYXRpb24gZm9yZWNhc3QgcHJvdmlkZWQsIHdoYXQgZG8geW91IHRoaW5rIGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBpbmZsYXRpb24gZW5kaW5nIHVwIGhpZ2hlciB0aGFuIDYlP1wNCkRlZmluaXRpdmUgQ29ycmVjdCBBbnN3ZXIgLSAzXA0KdmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSAmIHByb3BvcnRpb24gdGVzdFwNCioqUmVzdWx0OiBUaGUgYmVsbCBjdXJ2ZSBhbmQgdGhlIGNvbnRyb2wgZ3JvdXAgaGFzIHNob3duIHNpZ25pZmljYW50IGRpZmZlcmVuY2UuIFRoZSBtYWpvcml0eSBwZW9wbGUgdGhpbmsgdGhlIHByb2JhYmlsaXR5IGlzIGV4dHJlbWVseSBsb3cgKGxlc3MgdGhhbiAxJSkuKipcDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3ExMSA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMTFfbGlzdCA8LSBsaXN0KCJRNC4xMSIsIlE2LjExIiwgIlE4LjExIiwgIlExMC4xMSIsICJRMTIuMTEiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9xMTFfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoInExMV92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xMTEgPC0gcmJpbmQoc3VydmV5X3ExMSwgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9xMTEkcTExX3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X3ExMSRxMTFfdmFsdWUpDQoNCmBgYA0KDQpUZXN0IHRoZSBwcm9wb3J0aW9uIG9mIGNvcnJlY3QgYW5zd2VyDQpgYGB7cn0NCnN1cnZleV9xMTFfY29udGluZ2VuY3kgPC0gdGFibGUoc3VydmV5X3ExMSRxMTFfdmFsdWUsIHN1cnZleV9xMTEkZ3JvdXApDQojIHByaW50IHRoZSBjb250aW5nZW5jeSB0YWJsZQ0KcHJpbnQoc3VydmV5X3ExMV9jb250aW5nZW5jeSkNCnN1cnZleV9xMTFfY29ycmVjdCA8LSBzdXJ2ZXlfcTExX2NvbnRpbmdlbmN5WzMsXQ0Kc3VydmV5X3ExMV9ncm91cF90b3RhbCA8LSBjb2xTdW1zKHN1cnZleV9xMTFfY29udGluZ2VuY3kpDQpwcm9wLnRlc3Qoc3VydmV5X3ExMV9jb3JyZWN0LCBzdXJ2ZXlfcTExX2dyb3VwX3RvdGFsKQ0KDQpgYGANClBvc3QtaG9jIHRlc3QNCmBgYHtyfQ0KcGFpcndpc2UucHJvcC50ZXN0KA0KICB4ID0gc3VydmV5X3ExMV9jb250aW5nZW5jeVszLCBdLA0KICBuID0gY29sU3VtcyhzdXJ2ZXlfcTExX2NvbnRpbmdlbmN5KSwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiICMgb3IgImhvbG0iLCAiQkgiDQopDQpgYGANClBsb3QgcHJvYmFiaWxpdHkgb2YgaGlnaGVyIHRoYW4gNiUgcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQpzdXJ2ZXlfcTExX3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUoc3VydmV5X3ExMV9jb250aW5nZW5jeSkNCiMgcmVuYW1lIGNvbHVtbnMNCm5hbWVzKHN1cnZleV9xMTFfcHJvcCkgPC0gYygiUXh4LjExIiwgIkdyb3VwIiwgIkNvdW50IikNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpzdXJ2ZXlfcTExX3Byb3AgPC0gc3VydmV5X3ExMV9wcm9wICU+JQ0KICBtdXRhdGUoUXh4LjExX2xhYmVsID0gY2FzZV93aGVuKA0KICAgIFF4eC4xMSA9PSAiMSIgfiAiMS1Nb3JlIHRoYW4gMjAlIiwNCiAgICBReHguMTEgPT0gIjIiIH4gIjMtNS0xMCUiLA0KICAgIFF4eC4xMSA9PSAiMyIgfiAiNC0xLTUlIiwNCiAgICBReHguMTEgPT0gIjQiIH4gIjUtTGVzcyB0aGFuIDElIiwNCiAgICBReHguMTEgPT0gIjUiIH4gIjItMTAtMjAlIg0KICApKQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnN1cnZleV9xMTFfcHJvcCA8LSBzdXJ2ZXlfcTExX3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3Qoc3VydmV5X3ExMV9wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUXh4LjExX2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofkdyb3VwKSsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMTEgUHJvYmFiaWxpdHkgb2YgaGlnaGVyIHRoYW4gNiUgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KUGxvdCB0aGUgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgZm9yY2Ugb3JkZXIgZm9yIGdyYXBoDQpzdXJ2ZXlfcTExIDwtIHN1cnZleV9xMTEgJT4lDQogIG11dGF0ZSgNCiAgICBxMTFfdmFsdWVfcmUgPSBmYWN0b3IoDQogICAgICBxMTFfdmFsdWUsDQogICAgICBsZXZlbHMgPSBjKDEsIDUsIDIsIDMsIDQpDQogICAgKQ0KICApDQojIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KZ2dwbG90KHN1cnZleV9xMTEsIGFlcyh4ID0gcTExX3ZhbHVlX3JlKSkgKw0KICBnZW9tX2JhcihmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlF4eC4xMSBSZXNwb25zZXMgKGZvcmNlZCAxLTUtMi0zLTQgb3JkZXIpIiwNCiAgICB4ICAgICA9ICJReHguMTEiLA0KICAgIHkgICAgID0gIkNvdW50Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCiMjIFF4eC4xMiBQcm9iYWJpbGl0eSBvZiBoaWdoZXIgdGhhbiAzJSANCkJhc2VkIG9uIHRoZSBpbmZsYXRpb24gZm9yZWNhc3QgcHJvdmlkZWQsIHdoYXQgZG8geW91IHRoaW5rIGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBpbmZsYXRpb24gZW5kaW5nIHVwIGhpZ2hlciB0aGFuIDMlP1wNCkRlZmluaXRpdmUgQ29ycmVjdCBBbnN3ZXIgLSAxXA0KdmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSAmIHByb3BvcnRpb24gdGVzdFwNCioqUmVzdWx0OiBUaGVyZSBpcyBubyBzdGF0aXN0aWNhbCBkaWZmZXJlbmNlIGFuZCB0aGUgbWFqb3JpdHkgcGVvcGxlIGRpZG4ndCBnZXQgdGhlIGFuc3dlciByaWdodC4qKg0KYGBge3J9DQojIGNvbWJpbmUgZGF0YSBmcm9tIGRpZmZlcmVudCBncm91cHMNCnN1cnZleV9xMTIgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTEyX2xpc3QgPC0gbGlzdCgiUTQuMTIiLCJRNi4xMiIsICJROC4xMiIsICJRMTAuMTIiLCAiUTEyLjEyIikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTEyX2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxMTJfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTEyIDwtIHJiaW5kKHN1cnZleV9xMTIsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTEyJHExMl92YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xMTIkcTEyX3ZhbHVlKQ0KDQpgYGANCg0KVGVzdCB0aGUgcHJvcG9ydGlvbiBvZiBjb3JyZWN0IGFuc3dlcg0KYGBge3J9DQpzdXJ2ZXlfcTEyX2NvbnRpbmdlbmN5IDwtIHRhYmxlKHN1cnZleV9xMTIkcTEyX3ZhbHVlLCBzdXJ2ZXlfcTEyJGdyb3VwKQ0KIyBwcmludCB0aGUgY29udGluZ2VuY3kgdGFibGUNCnByaW50KHN1cnZleV9xMTJfY29udGluZ2VuY3kpDQoNCnN1cnZleV9xMTJfY29ycmVjdCA8LSBzdXJ2ZXlfcTEyX2NvbnRpbmdlbmN5WzIsXQ0Kc3VydmV5X3ExMl9ncm91cF90b3RhbCA8LSBjb2xTdW1zKHN1cnZleV9xMTJfY29udGluZ2VuY3kpDQpwcm9wLnRlc3Qoc3VydmV5X3ExMl9jb3JyZWN0LCBzdXJ2ZXlfcTEyX2dyb3VwX3RvdGFsKQ0KYGBgDQpQbG90IHByb2JhYmlsaXR5IG9mIGhpZ2hlciB0aGFuIDMlIHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0Kc3VydmV5X3ExMl9wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHN1cnZleV9xMTJfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhzdXJ2ZXlfcTEyX3Byb3ApIDwtIGMoIlF4eC4xMiIsICJHcm91cCIsICJDb3VudCIpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0Kc3VydmV5X3ExMl9wcm9wIDwtIHN1cnZleV9xMTJfcHJvcCAlPiUNCiAgbXV0YXRlKFF4eC4xMl9sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBReHguMTIgPT0gIjEiIH4gIjEtTW9yZSB0aGFuIDYwJSIsDQogICAgUXh4LjEyID09ICIyIiB+ICIzLTQwLTUwJSIsDQogICAgUXh4LjEyID09ICIzIiB+ICI0LTMwLTQwJSIsDQogICAgUXh4LjEyID09ICI0IiB+ICI1LUxlc3MgdGhhbiAzMCUiLA0KICAgIFF4eC4xMiA9PSAiNSIgfiAiMi01MC02MCUiDQogICkpDQojIGNhbGN1bGF0ZSBwcm9wb3J0aW9ucyB3aXRoaW4gZWFjaCBncm91cA0Kc3VydmV5X3ExMl9wcm9wIDwtIHN1cnZleV9xMTJfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoR3JvdXApICU+JQ0KICBtdXRhdGUoUHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkNCmdncGxvdChzdXJ2ZXlfcTEyX3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBReHguMTJfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+R3JvdXApKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlF4eC4xMiBQcm9iYWJpbGl0eSBvZiBoaWdoZXIgdGhhbiAzJSBQcm9wb3Rpb24gUGxvdCBhY3Jvc3MgR3JvdXBzIiwNCiAgICB4ID0gIlJlc3BvbnNlIiwNCiAgICB5ID0gIlByb3BvcnRpb24iDQogICkgKw0KICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQpQbG90IHRoZSBoaXN0b2dyYW0gaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0KIyBmb3JjZSBvcmRlciBmb3IgZ3JhcGgNCnN1cnZleV9xMTIgPC0gc3VydmV5X3ExMiAlPiUNCiAgbXV0YXRlKA0KICAgIHExMl92YWx1ZV9yZSA9IGZhY3RvcigNCiAgICAgIHExMl92YWx1ZSwNCiAgICAgIGxldmVscyA9IGMoMSwgNSwgMiwgMywgNCkNCiAgICApDQogICkNCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X3ExMiwgYWVzKHggPSBxMTJfdmFsdWVfcmUpKSArDQogIGdlb21fYmFyKGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUXh4LjEyIFJlc3BvbnNlcyAoZm9yY2VkIDEtNS0yLTMtNCBvcmRlcikiLA0KICAgIHggICAgID0gIlF4eC4xMiIsDQogICAgeSAgICAgPSAiQ291bnQiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojIyAhIFF4eC4xNCBQcm9iYWJpbGl0eSBvZiBoaWdoZXIgdGhhbiAyJSB0YXJnZXQNClRvIGtlZXAgaW5mbGF0aW9uIGxvdyBhbmQgc3RhYmxlLCBHb3Zlcm5tZW50IHNldHMgYW4gaW5mbGF0aW9uIHRhcmdldCBvZiAyJS4gIEJhc2VkIG9uIHRoZSBpbmZsYXRpb24gZm9yZWNhc3QgcHJvdmlkZWQsIHdoYXQgZG8geW91IHRoaW5rIGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBpbmZsYXRpb24gZXhjZWVkaW5nIDIlP1wNCkRlZmluaXRpdmUgQ29ycmVjdCBBbnN3ZXIgLSAzXA0KdmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSAmIHByb3BvcnRpb24gdGVzdFwNCioqUmVzdWx0OiBDb250cm9sIGdyb3VwIGlzIHNpZ25pZmljYW50IGRpZmZlcmVudCBmcm9tIGVycm9yIEJhciBncm91cCBhbmQgYmVsbCBjdXJ2ZSBncm91cDsgRXJyb3IgYmFyIGdyb3VwIGhhcyBzaG93biBzdGF0aXN0aWNhbCBkaWZmZXJlbmNlIGNvbXBhcmVkIHRvIGZhbiBjaGFydCBzbGljZS4gNDQlIG9mIHRvdGFsIHJlc3BvbmRlbnRzIGNhbiB1bmRlcnN0YW5kIHRoZSBwcm9iYWJpbGl0eSBvZiBpbmZsYXRpb24gYmVpbmcgaGlnaGVyIHRoYW4gNiUgY29ycmVjdGx5LioqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3ExNCA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMTRfbGlzdCA8LSBsaXN0KCJRNC4xNCIsIlE2LjE0IiwgIlE4LjE0IiwgIlExMC4xNCIsICJRMTIuMTQiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9xMTRfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoInExNF92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xMTQgPC0gcmJpbmQoc3VydmV5X3ExNCwgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9xMTQkcTE0X3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X3ExNCRxMTRfdmFsdWUpDQpgYGANClRlc3QgdGhlIHByb3BvcnRpb24gb2YgY29ycmVjdCBhbnN3ZXINCmBgYHtyfQ0Kc3VydmV5X3ExNF9jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfcTE0JHExNF92YWx1ZSwgc3VydmV5X3ExNCRncm91cCkNCiMgcHJpbnQgdGhlIGNvbnRpbmdlbmN5IHRhYmxlDQpwcmludChzdXJ2ZXlfcTE0X2NvbnRpbmdlbmN5KQ0KDQpzdXJ2ZXlfcTE0X2NvcnJlY3QgPC0gc3VydmV5X3ExNF9jb250aW5nZW5jeVszLF0NCnN1cnZleV9xMTRfZ3JvdXBfdG90YWwgPC0gY29sU3VtcyhzdXJ2ZXlfcTE0X2NvbnRpbmdlbmN5KQ0KcHJvcC50ZXN0KHN1cnZleV9xMTRfY29ycmVjdCwgc3VydmV5X3ExNF9ncm91cF90b3RhbCkNCmBgYA0KUGFpcndpc2UgcHJvcG9ydGlvbiB0ZXN0DQpgYGB7cn0NCnBhaXJ3aXNlLnByb3AudGVzdCgNCiAgeCA9IHN1cnZleV9xMTRfY29udGluZ2VuY3lbMywgXSwNCiAgbiA9IGNvbFN1bXMoc3VydmV5X3ExNF9jb250aW5nZW5jeSksDQogIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiAjIG9yICJob2xtIiwgIkJIIg0KKQ0KYGBgDQpQbG90IHByb2JhYmlsaXR5IG9mIGhpZ2hlciB0aGFuIDIlIHRhcmdldCBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnN1cnZleV9xMTRfcHJvcCAgPC0gYXMuZGF0YS5mcmFtZShzdXJ2ZXlfcTE0X2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMoc3VydmV5X3ExNF9wcm9wKSA8LSBjKCJReHguMTQiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnN1cnZleV9xMTRfcHJvcCA8LSBzdXJ2ZXlfcTE0X3Byb3AgJT4lDQogIG11dGF0ZShReHguMTRfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgUXh4LjE0ID09ICIxIiB+ICIxLT45OSUiLA0KICAgIFF4eC4xNCA9PSAiMiIgfiAiMi1hcm91bmQgODAlIiwNCiAgICBReHguMTQgPT0gIjMiIH4gIjMtYXJvdW5kIDYwJSIsDQogICAgUXh4LjE0ID09ICI0IiB+ICI0LWFyb3VuZCA1MCUiLA0KICAgIFF4eC4xNCA9PSAiNSIgfiAiNS1hcm91bmQgMzAlIiwNCiAgICBReHguMTQgPT0gIjYiIH4gIjYtYXJvdW5kIDIwJSIsDQogICAgUXh4LjE0ID09ICI3IiB+ICI3LTwxJSINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpzdXJ2ZXlfcTE0X3Byb3AgPC0gc3VydmV5X3ExNF9wcm9wICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gQ291bnQgLyBzdW0oQ291bnQpKQ0KDQpnZ3Bsb3Qoc3VydmV5X3ExNF9wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUXh4LjE0X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofkdyb3VwKSsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMTQgUHJvYmFiaWxpdHkgb2YgaGlnaGVyIHRoYW4gMiUgdGFyZ2V0IFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgdGhlIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQojIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KZ2dwbG90KHN1cnZleV9xMTQsIGFlcyh4ID0gcTE0X3ZhbHVlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogICMgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnModGl0bGUgPSAiUXh4LjE0IFByb2JhYmlsaXR5IG9mIGhpZ2hlciB0aGFuIDIlIHRhcmdldCBIaXN0b2dyYW0iLA0KICAgICAgIHggPSAiUXh4LjE0IiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIG1heChzdXJ2ZXlfcTE0JHExNF92YWx1ZSwgbmEucm0gPSBUUlVFKSwgYnkgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojIyBReHguMTUgRGV2aWF0aW9uIGZyb20gY2VudHJhbCBlc3RpbWF0ZQ0KQmFzZWQgb24gdGhlIGluZmxhdGlvbiBmb3JlY2FzdCBwcm92aWRlZCwgZG8geW91IHRoaW5rIHRoZXJlIGlzIGEgaGlnaGVyIHJpc2sgb2YgaW5mbGF0aW9uIGluIDIwMjZRMiBleGNlZWRpbmcgdGhlIGNlbnRyYWwgZXN0aW1hdGUgb3Igb2YgYmVpbmcgbGVzcyB0aGFuIHRoaXMgY2VudHJhbCBlc3RpbWF0ZT9cDQpEZWZpbml0aXZlIENvcnJlY3QgQW5zd2VyIC0gM1wNCnZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgJiBwcm9wb3J0aW9uIHRlc3RcDQoqKlJlc3VsdDogVGhlIGNvbnRyb2wgZ3JvdXAgc2hvd3Mgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBjb21wYXJlZCB0byB0aGUgc2hhZGVkIGJhciBncm91cCBpbiB0ZXJtcyBvZiB0aGUgY29ycmVjdGx5IGNob29zaW5nIHVuZGVyc3RhbmRpbmcgdGhlIHJpc2sgaXMgZXF1YWwuIEFtb25nIGFsbCBwYXJ0aWNpcGFudHMsIG9ubHkgYXJvdW5kIDglIHJlc3BvbmRlbnRzIHRoaW5rIHRoZXJlIGlzIGRvd25zaWRlIHJpc2suIFRoZSBsYXJnZXN0IHByb3BvcnRpb24gKDQ4JSkgb2YgcGFydGljaXBhbnRzIGJlbGlldmUgdGhlcmUgaXMgdXBzaWRlIHJpc2suICoqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3ExNSA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMTVfbGlzdCA8LSBsaXN0KCJRNC4xNSIsIlE2LjE1IiwgIlE4LjE1IiwgIlExMC4xNSIsICJRMTIuMTUiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9xMTVfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoInExNV92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xMTUgPC0gcmJpbmQoc3VydmV5X3ExNSwgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9xMTUkcTE1X3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X3ExNSRxMTVfdmFsdWUpDQpgYGANCg0KQ29udGluZ2VuY3kgdGFibGUNCmBgYHtyfQ0Kc3VydmV5X3ExNV9jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfcTE1JHExNV92YWx1ZSwgc3VydmV5X3ExNSRncm91cCkNCiMgcHJpbnQgdGhlIGNvbnRpbmdlbmN5IHRhYmxlDQpwcmludChzdXJ2ZXlfcTE1X2NvbnRpbmdlbmN5KQ0KIyBjaGktc3F1YXJlZCB0ZXN0DQpjaGlzcV9yZXN1bHQgPC0gY2hpc3EudGVzdChzdXJ2ZXlfcTE1X2NvbnRpbmdlbmN5KQ0Kc3RkX3Jlc2lkIDwtIGNoaXNxX3Jlc3VsdCRzdGRyZXMNCnByaW50KHN0ZF9yZXNpZCkNCg0KIyBjb3JyZWN0IGFuc3dlcg0Kc3VydmV5X3ExNV9jb3JyZWN0IDwtIHN1cnZleV9xMTVfY29udGluZ2VuY3lbMyxdDQpzdXJ2ZXlfcTE1X2dyb3VwX3RvdGFsIDwtIGNvbFN1bXMoc3VydmV5X3ExNV9jb250aW5nZW5jeSkNCnByb3AudGVzdChzdXJ2ZXlfcTE1X2NvcnJlY3QsIHN1cnZleV9xMTVfZ3JvdXBfdG90YWwpDQpgYGANClBhaXJ3aXNlIHByb3BvcnRpb24gdGVzdA0KYGBge3J9DQpwYWlyd2lzZS5wcm9wLnRlc3QoDQogIHggPSBzdXJ2ZXlfcTE1X2NvbnRpbmdlbmN5WzMsIF0sDQogIG4gPSBjb2xTdW1zKHN1cnZleV9xMTVfY29udGluZ2VuY3kpLA0KICBwLmFkanVzdC5tZXRob2QgPSAiYm9uZmVycm9uaSIgIyBvciAiaG9sbSIsICJCSCINCikNCmBgYA0KDQoNClBsb3QgcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQpzdXJ2ZXlfcTE1X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUoc3VydmV5X3ExNV9jb250aW5nZW5jeSkNCiMgcmVuYW1lIGNvbHVtbnMNCm5hbWVzKHN1cnZleV9xMTVfcHJvcCkgPC0gYygiUXh4LjE1IiwgIkdyb3VwIiwgIkNvdW50IikNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpzdXJ2ZXlfcTE1X3Byb3AgPC0gc3VydmV5X3ExNV9wcm9wICU+JQ0KICBtdXRhdGUoUXh4LjE1X2xhYmVsID0gY2FzZV93aGVuKA0KICAgIFF4eC4xNSA9PSAiMSIgfiAiMS1iaWdnZXIgdXBzaWRlIHJpc2siLA0KICAgIFF4eC4xNSA9PSAiMiIgfiAiMi1iaWdnZXIgZG93bnNpZGUgcmlzayIsDQogICAgUXh4LjE1ID09ICIzIiB+ICIzLWVxdWFsIHJpc2tzIG9uIGJvdGggc2lkZXMiDQogICkpDQojIGNhbGN1bGF0ZSBwcm9wb3J0aW9ucyB3aXRoaW4gZWFjaCBncm91cA0Kc3VydmV5X3ExNV9wcm9wIDwtIHN1cnZleV9xMTVfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoR3JvdXApICU+JQ0KICBtdXRhdGUoUHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkNCmdncGxvdChzdXJ2ZXlfcTE1X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBReHguMTVfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+R3JvdXApKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlF4eC4xNSBBbnN3ZXIgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KUGxvdCB0aGUgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X3ExNSwgYWVzKHggPSBxMTVfdmFsdWUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicyh0aXRsZSA9ICJReHguMTUgQW5zd2VyIEJhciBDaGFydCIsDQogICAgICAgeCA9ICJReHguMTUiLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHN1cnZleV9xMTUkcTE1X3ZhbHVlLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQojIyBReHguMTcgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGV4YWN0bHkgMi42JQ0KSG93IGxpa2VseSBkbyB5b3UgdGhpbmsgaXQgaXMgdGhhdCB0aGUgaW5mbGF0aW9uIHdpbGwgYmUgZXhhY3RseSAyLjYlP1wNCiphc2NlbmRpbmcgdmFsdWUtaW5jcmVhc2luZyBsaWtlbGlob29kKlwNClZhcmlhYmxlOiB0cmVhdCBhcyBjb250aW51b3VzXA0KTWV0aG9kOiBLcnVza2FsLVdhbGxpcyB0ZXN0XA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuIFRoZSBvdmVyYWxsIGRpc3RyaWJ1dGlvbiBpcyBza2V3ZWQgdG93YXJkcyB1bmxpa2VseS4qKg0KYGBge3J9DQojIGNvbWJpbmUgZGF0YSBmcm9tIGRpZmZlcmVudCBncm91cHMNCnN1cnZleV9xMTcgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTE3X2xpc3QgPC0gbGlzdCgiUTQuMTdfMSIsIlE2LjE3XzEiLCAiUTguMTdfMSIsICJRMTAuMTdfMSIsICJRMTIuMTdfMSIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3ExN19saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygicTE3X3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X3ExNyA8LSByYmluZChzdXJ2ZXlfcTE3LCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X3ExNyRxMTdfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfcTE3JHExN192YWx1ZSkNCg0KYGBgDQoNCktXIHRlc3QNCmBgYHtyfQ0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X3ExNyRxMTdfdmFsdWUpDQoNCiMgcnVuIEtydXNrYWwtV2FsbGlzIHRlc3QNCmtydXNrYWxfdGVzdCA8LSBrcnVza2FsLnRlc3QocTE3X3ZhbHVlIH4gZ3JvdXAsIGRhdGEgPSBzdXJ2ZXlfcTE3KQ0KcHJpbnQoa3J1c2thbF90ZXN0KQ0KYGBgDQoNClBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X3ExNywgYWVzKHggPSBxMTdfdmFsdWUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicyh0aXRsZSA9ICJReHguMTcgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGV4YWN0bHkgMi42JSBkaXN0cmlidXRpb24iLA0KICAgICAgIHggPSAiUXh4LjE3IiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMubnVtZXJpYyhuYW1lcyhsaWtlbGlob29kX2xhYmVscykpLCANCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxpa2VsaWhvb2RfbGFiZWxzKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQoNCiMgR3JvdXBlZCBiYXItc3R5bGUgaGlzdG9ncmFtDQpnZ3Bsb3Qoc3VydmV5X3ExNywgYWVzKHggPSBmYWN0b3IocTE3X3ZhbHVlKSwgZmlsbCA9IGZhY3Rvcihncm91cCkpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICAjIGFkZCBsYWJlbHMNCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9bGlrZWxpaG9vZF9sYWJlbHMpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMTcgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGV4YWN0bHkgMi42JSBkaXN0cmlidXRpb24gYnkgZ3JvdXAiLA0KICAgIHggPSAiUXh4LjE3IFJlc3BvbnNlIiwNCiAgICB5ID0gIkNvdW50IiwNCiAgICBmaWxsID0gIkdyb3VwIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQojIyBReHguMjEgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGluZmxhdGlvbiBiZWluZyBiZXR3ZWVuIDEuOSUgYW5kIDMuMyUNCkhvdyBsaWtlbHkgZG8geW91IHRoaW5rIGl0IGlzIHRoYXQgdGhlIGluZmxhdGlvbiB3aWxsIGJlIGJldHdlZW4gMS45JSBhbmQgMy4zJT9cDQoqYXNjZW5kaW5nIHZhbHVlLWluY3JlYXNpbmcgbGlrZWxpaG9vZCpcDQpWYXJpYWJsZTogdHJlYXQgYXMgY29udGludW91c1wNCk1ldGhvZDogS3J1c2thbC1XYWxsaXMgdGVzdFwNCioqUmVzdWx0OiBGYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGUgbWFqb3JpdHkgb2YgcmVzcG9uZGVudHMgdGhpbmsgaXQncyBxdWl0ZSBsaWtlbHkuKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfcTIxIDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X3EyMV9saXN0IDwtIGxpc3QoIlE0LjIxXzEiLCJRNi4yMV8xIiwgIlE4LjIxXzEiLCAiUTEwLjIxXzEiLCAiUTEyLjIxXzEiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9xMjFfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoInEyMV92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xMjEgPC0gcmJpbmQoc3VydmV5X3EyMSwgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9xMjEkcTIxX3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X3EyMSRxMjFfdmFsdWUpDQpgYGANCg0KS1cgdGVzdA0KYGBge3J9DQojIGNoZWNrIG5vcm1hbGl0eSAtLT4gdGhlIGRhdGEgaXMgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkDQojIHNoYXBpcm8udGVzdChzdXJ2ZXlfcTIxJHEyMV92YWx1ZSkNCg0KIyBydW4gS3J1c2thbC1XYWxsaXMgdGVzdA0Ka3J1c2thbF90ZXN0IDwtIGtydXNrYWwudGVzdChxMjFfdmFsdWUgfiBncm91cCwgZGF0YSA9IHN1cnZleV9xMjEpDQpwcmludChrcnVza2FsX3Rlc3QpDQpgYGANClBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgR3JvdXBlZCBiYXItc3R5bGUgaGlzdG9ncmFtDQpnZ3Bsb3Qoc3VydmV5X3EyMSwgYWVzKHggPSBmYWN0b3IocTIxX3ZhbHVlKSwgZmlsbCA9IGZhY3Rvcihncm91cCkpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICAjIGFkZCBsYWJlbHMNCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9bGlrZWxpaG9vZF9sYWJlbHMpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMjEgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGluZmxhdGlvbiBiZWluZyBiZXR3ZWVuIDEuOSUgYW5kIDMuMyUgZGlzdHJpYnV0aW9uIGJ5IGdyb3VwIiwNCiAgICB4ID0gIlF4eC4yMSBSZXNwb25zZSIsDQogICAgeSA9ICJDb3VudCIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KUGxvdCBiYXIgY2hhcnQgaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0KIyBoaXN0b2dyYW0gaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmdncGxvdChzdXJ2ZXlfcTIxLCBhZXMoeCA9IHEyMV92YWx1ZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICBsYWJzKHRpdGxlID0gIlF4eC4yMSBTZWxmLXJlcG9ydGVkIGxpa2VsaWhvb2Qgb2YgaW5mbGF0aW9uIGJlaW5nIGJldHdlZW4gMS45JSBhbmQgMy4zJSBkaXN0cmlidXRpb24iLA0KICAgICAgIHggPSAiUXh4LjIxIiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMubnVtZXJpYyhuYW1lcyhsaWtlbGlob29kX2xhYmVscykpLCANCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxpa2VsaWhvb2RfbGFiZWxzKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCiMjICEgUXh4LjIyIFNlbGYtcmVwb3J0ZWQgbGlrZWxpaG9vZCBvZiBpbmZsYXRpb24gYmVpbmcgYmV0d2VlbiAzLjMlIGFuZCA1LjYlDQpIb3cgbGlrZWx5IGRvIHlvdSB0aGluayBpdCBpcyB0aGF0IHRoZSBpbmZsYXRpb24gd2lsbCBiZSBiZXR3ZWVuIDMuMyUgYW5kIDUuNiU/XA0KKmFzY2VuZGluZyB2YWx1ZS1pbmNyZWFzaW5nIGxpa2VsaWhvb2QqXA0KVmFyaWFibGU6IHRyZWF0IGFzIGNvbnRpbnVvdXNcDQpNZXRob2Q6IEtydXNrYWwtV2FsbGlzIHRlc3RcDQoqKlJlc3VsdDogVGhlIGRpc3RyaWJ1dGlvbiBvZiBzaGFkZWQgYmFyIGdyb3VwIGFuZCBiZWxsIGN1cnZlIHNob3cgc3RhdGlzdGljYWwgZGlmZmVyZW5jZS4gTmVhciBoYWxmIG9mIHRoZSByZXNwb25kZW50cyB0aGluayBpdCdzIHF1aXRlIHVubGlrZWx5LioqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3EyMiA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMjJfbGlzdCA8LSBsaXN0KCJRNC4yMl8xIiwiUTYuMjJfMSIsICJROC4yMl8xIiwgIlExMC4yMl8xIiwgIlExMi4yMl8xIikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTIyX2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxMjJfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTIyIDwtIHJiaW5kKHN1cnZleV9xMjIsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTIyJHEyMl92YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xMjIkcTIyX3ZhbHVlKQ0KYGBgDQoNCktXIHRlc3QNCmBgYHtyfQ0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X3EyMiRxMjJfdmFsdWUpDQoNCiMgcnVuIEtydXNrYWwtV2FsbGlzIHRlc3QNCmtydXNrYWxfdGVzdCA8LSBrcnVza2FsLnRlc3QocTIyX3ZhbHVlIH4gZ3JvdXAsIGRhdGEgPSBzdXJ2ZXlfcTIyKQ0KcHJpbnQoa3J1c2thbF90ZXN0KQ0KDQojIFBvc3QtaG9jIHRlc3QNCmR1bm5UZXN0KHEyMl92YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X3EyMiwgbWV0aG9kID0gImJvbmZlcnJvbmkiKQ0KYGBgDQoNClBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgR3JvdXBlZCBiYXItc3R5bGUgaGlzdG9ncmFtDQpnZ3Bsb3Qoc3VydmV5X3EyMiwgYWVzKHggPSBmYWN0b3IocTIyX3ZhbHVlKSwgZmlsbCA9IGZhY3Rvcihncm91cCkpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICAjIGFkZCBsYWJlbHMNCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9bGlrZWxpaG9vZF9sYWJlbHMpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMjIgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGluZmxhdGlvbiBiZWluZyBiZXR3ZWVuIDMuMyUgYW5kIDUuNiUgZGlzdHJpYnV0aW9uIGJ5IGdyb3VwIiwNCiAgICB4ID0gIlF4eC4yMiBSZXNwb25zZSIsDQogICAgeSA9ICJDb3VudCIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgYmFyIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X3EyMiwgYWVzKHggPSBxMjJfdmFsdWUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicyh0aXRsZSA9ICJReHguMjIgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGluZmxhdGlvbiBiZWluZyBiZXR3ZWVuIDMuMyUgYW5kIDUuNiUgZGlzdHJpYnV0aW9uIiwNCiAgICAgICB4ID0gIlF4eC4yMiIsDQogICAgICAgeSA9ICJDb3VudCIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGFzLm51bWVyaWMobmFtZXMobGlrZWxpaG9vZF9sYWJlbHMpKSwgDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsaWtlbGlob29kX2xhYmVscykgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQojIyBReHguMjMgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGluZmxhdGlvbiBiZWluZyBoaWdoZXIgdGhhbiAzJQ0KSG93IGxpa2VseSBkbyB5b3UgdGhpbmsgaXQgaXMgdGhhdCB0aGUgaW5mbGF0aW9uIHdpbGwgYmUgaGlnaGVyIHRoYW4gMyU/XA0KKmFzY2VuZGluZyB2YWx1ZS1pbmNyZWFzaW5nIGxpa2VsaWhvb2QqXA0KVmFyaWFibGU6IHRyZWF0IGFzIGNvbnRpbnVvdXNcDQpNZXRob2Q6IEtydXNrYWwtV2FsbGlzIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gVGhlIG1ham9yaXR5IG9mIHJlc3BvbmRlbnRzIHRoaW5rIGl0J3MgcXVpdGUgdW5saWtlbHksIGJ1dCB0aGVyZSBpcyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlLioqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3EyMyA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMjNfbGlzdCA8LSBsaXN0KCJRNC4yM18xIiwiUTYuMjNfMSIsICJROC4yM18xIiwgIlExMC4yM18xIiwgIlExMi4yM18xIikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTIzX2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxMjNfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTIzIDwtIHJiaW5kKHN1cnZleV9xMjMsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTIzJHEyM192YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xMjMkcTIzX3ZhbHVlKQ0KYGBgDQpLVyB0ZXN0DQpgYGB7cn0NCiMgY2hlY2sgbm9ybWFsaXR5IC0tPiB0aGUgZGF0YSBpcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQNCiMgc2hhcGlyby50ZXN0KHN1cnZleV9xMjMkcTIzX3ZhbHVlKQ0KDQojIHJ1biBLcnVza2FsLVdhbGxpcyB0ZXN0DQprcnVza2FsX3Rlc3QgPC0ga3J1c2thbC50ZXN0KHEyM192YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X3EyMykNCnByaW50KGtydXNrYWxfdGVzdCkNCmBgYA0KUGxvdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0KIyBHcm91cGVkIGJhci1zdHlsZSBoaXN0b2dyYW0NCmdncGxvdChzdXJ2ZXlfcTIzLCBhZXMoeCA9IGZhY3RvcihxMjNfdmFsdWUpLCBmaWxsID0gZmFjdG9yKGdyb3VwKSkpICsNCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogICMgYWRkIGxhYmVscw0KICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1saWtlbGlob29kX2xhYmVscykgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlF4eC4yMyBTZWxmLXJlcG9ydGVkIGxpa2VsaWhvb2Qgb2YgaW5mbGF0aW9uIGJlaW5nIGhpZ2hlciB0aGFuIDMlIGRpc3RyaWJ1dGlvbiBieSBncm91cCIsDQogICAgeCA9ICJReHguMjMgUmVzcG9uc2UiLA0KICAgIHkgPSAiQ291bnQiLA0KICAgIGZpbGwgPSAiR3JvdXAiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQpQbG90IGJhciBjaGFydCBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQojIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KZ2dwbG90KHN1cnZleV9xMjMsIGFlcyh4ID0gcTIzX3ZhbHVlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogICMgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnModGl0bGUgPSAiUXh4LjIzIFNlbGYtcmVwb3J0ZWQgbGlrZWxpaG9vZCBvZiBpbmZsYXRpb24gYmVpbmcgaGlnaGVyIHRoYW4gMyUgZGlzdHJpYnV0aW9uIiwNCiAgICAgICB4ID0gIlF4eC4yMyIsDQogICAgICAgeSA9ICJDb3VudCIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGFzLm51bWVyaWMobmFtZXMobGlrZWxpaG9vZF9sYWJlbHMpKSwgDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsaWtlbGlob29kX2xhYmVscykgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQoNCg0KIyMgUXh4LjI2IEFjY3VyYWN5IG9mIGNlbnRyYWwgZXN0aW1hdGUNCk9uIGEgc2NhbGUgb2YgMSB0byAxMCwgd2hlcmUgMSBtZWFucyBub3QgYWNjdXJhdGUgYXQgYWxsIGFuZCAxMCBtZWFucyB2ZXJ5IGFjY3VyYXRlLCBob3cgYWNjdXJhdGUgZG8geW91IHRoaW5rIHRoZSBjZW50cmFsIGVzdGltYXRlIGluIHRoZSBncmFwaCBpcz9cDQoqMS1Ob3QgYWNjdXJhdGUgYXQgYWxsOyAxMC1WZXJ5IGFjY3VyYXRlKlwNClZhcmlhYmxlOiBjb250aW51b3VzXA0KTWV0aG9kOiBBTk5PVkEgdGVzdCBvciBLVyB0ZXN0IChkZXBlbmRzIG9uIHdoZXRoZXIgaXQncyBub3JtYWxseSBkaXN0cmlidXRlZClcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4qKg0KYGBge3J9DQojIGNvbWJpbmUgZGF0YSBmcm9tIGRpZmZlcmVudCBncm91cHMNCnN1cnZleV9xMjYgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTI2X2xpc3QgPC0gbGlzdCgiUTQuMjZfMSIsIlE2LjI2XzEiLCAiUTguMjZfMSIsICJRMTAuMjZfMSIsICJRMTIuMjZfMSIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3EyNl9saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygicTI2X3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X3EyNiA8LSByYmluZChzdXJ2ZXlfcTI2LCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X3EyNiRxMjZfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfcTI2JHEyNl92YWx1ZSkNCmBgYA0KU3RhdGlzdGljYWwgdGVzdA0KYGBge3J9DQojIEluaXRpYWwgQ2hlY2sNCiMgc3VtbWFyeShzdXJ2ZXlfcTI2JHEyNl92YWx1ZSkNCg0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X3EyNiRxMjZfdmFsdWUpDQoNCiMgcnVuIEtydXNrYWwtV2FsbGlzIHRlc3QNCmtydXNrYWxfdGVzdCA8LSBrcnVza2FsLnRlc3QocTI2X3ZhbHVlIH4gZ3JvdXAsIGRhdGEgPSBzdXJ2ZXlfcTI2KQ0KcHJpbnQoa3J1c2thbF90ZXN0KQ0KDQpgYGANClN1bW1hcnkgc3RhdGlzdGljcw0KYGBge3J9DQojIFN1bW1hcnkgc3RhdGlzdGljcw0Kc3VydmV5X3EyNl9zdW1tYXJ5IDwtIHN1cnZleV9xMjYgJT4lDQogIGdyb3VwX2J5KGdyb3VwKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW4gPSBtZWFuKHEyNl92YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBtZWRpYW4gPSBtZWRpYW4ocTI2X3ZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgIHNkID0gc2QocTI2X3ZhbHVlLCBuYS5ybSA9IFRSVUUpDQogICkNCmBgYA0KDQoNClBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgR3JvdXBlZCBiYXItc3R5bGUgaGlzdG9ncmFtXA0KZ2dwbG90KHN1cnZleV9xMjYsIGFlcyh4ID0gZmFjdG9yKHEyNl92YWx1ZSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMjYgQWNjdXJhY3kgb2YgY2VudHJhbCBlc3RpbWF0ZSBkaXN0cmlidXRpb24gYnkgZ3JvdXAiLA0KICAgIHggPSAiUXh4LjI2IFJlc3BvbnNlIiwNCiAgICB5ID0gIkNvdW50IiwNCiAgICBmaWxsID0gIkdyb3VwIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQojIyBReHguMjcgQ2VydGFpbnR5IG9mIGNlbnRyYWwgZXN0aW1hdGUNCk9uIGEgc2NhbGUgb2YgMSB0byAxMCwgd2hlcmUgMSBtZWFucyB2ZXJ5IHVuY2VydGFpbiBhbmQgMTAgbWVhbnMgdmVyeSBjZXJ0YWluLCBob3cgY2VydGFpbiBvciB1bmNlcnRhaW4gZG8geW91IHRoaW5rIHRoZSBpbmZsYXRpb24gZm9yZWNhc3QgZm9yIDIwMjYgUTIgaXM/XA0KKjEtVmVyeSB1bmNlcnRhaW47IDEwLVZlcnkgY2VydGFpbipcDQpWYXJpYWJsZTogY29udGludW91c1wNCk1ldGhvZDogQU5OT1ZBIHRlc3Qgb3IgS1cgdGVzdCAoZGVwZW5kcyBvbiB3aGV0aGVyIGl0J3Mgbm9ybWFsbHkgZGlzdHJpYnV0ZWQpXA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuICoqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3EyNyA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMjdfbGlzdCA8LSBsaXN0KCJRNC4yN18xIiwiUTYuMjdfMSIsICJROC4yN18xIiwgIlExMC4yN18xIiwgIlExMi4yN18xIikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTI3X2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxMjdfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTI3IDwtIHJiaW5kKHN1cnZleV9xMjcsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTI3JHEyN192YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xMjckcTI3X3ZhbHVlKQ0KYGBgDQpTdGF0aXN0aWNhbCB0ZXN0DQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0KIyBzdW1tYXJ5KHN1cnZleV9xMjckcTI3X3ZhbHVlKQ0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X3EyNyRxMjdfdmFsdWUpDQojIHJ1biBLcnVza2FsLVdhbGxpcyB0ZXN0DQprcnVza2FsX3Rlc3QgPC0ga3J1c2thbC50ZXN0KHEyN192YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X3EyNykNCnByaW50KGtydXNrYWxfdGVzdCkNCmBgYA0KU3VtbWFyeSBzdGF0aXN0aWNzDQpgYGB7cn0NCiMgU3VtbWFyeSBzdGF0aXN0aWNzDQpzdXJ2ZXlfcTI3X3N1bW1hcnkgPC0gc3VydmV5X3EyNyAlPiUNCiAgZ3JvdXBfYnkoZ3JvdXApICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbiA9IG1lYW4ocTI3X3ZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgIG1lZGlhbiA9IG1lZGlhbihxMjdfdmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgc2QgPSBzZChxMjdfdmFsdWUsIG5hLnJtID0gVFJVRSkNCiAgKQ0KYGBgDQpQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQojIEdyb3VwZWQgYmFyLXN0eWxlIGhpc3RvZ3JhbQ0KZ2dwbG90KHN1cnZleV9xMjcsIGFlcyh4ID0gZmFjdG9yKHEyN192YWx1ZSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUXh4LjI3IFRoZSBkaXN0cmlidXRpb24gb2YgY2VhcnRhaW50eS91bmNlcnRhaW50eSBvZiB0aGUgY2VudHJhbCBlc3RpbWF0ZSBieSBncm91cCIsDQogICAgeCA9ICJReHguMjcgUmVzcG9uc2UiLA0KICAgIHkgPSAiQ291bnQiLA0KICAgIGZpbGwgPSAiR3JvdXAiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCiMjIFF4eC4yOSBSZXByZXNlbnRhdGl2ZW5lc3Mgb2YgdGhlIHVuY2VydGFpbnR5DQpPbiBhIHNjYWxlIG9mIDEgdG8gMTAsIHdoZXJlIDEgbWVhbnMgbm90IHJlcHJlc2VudGF0aXZlIGF0IGFsbCBhbmQgMTAgbWVhbnMgdmVyeSByZXByZXNlbnRhdGl2ZSwgaG93IHJlcHJlc2VudGF0aXZlIGRvIHlvdSB0aGluayB0aGUgdW5jZXJ0YWludHkgYmVpbmcgY29tbXVuaWNhdGVkIGlzIChpLmUuLCBob3cgd2VsbCB0aGUgZ2l2ZW4gaW5mb3JtYXRpb24gcmVmbGVjdHMgdGhlIHRydWUgdmFyaWFiaWxpdHkgb3IgdW5jZXJ0YWludHkgb2YgdGhlIGZvcmVjYXN0PylcDQoqMS1Ob3QgcmVwcmVzZW50YXRpdmUgYXQgYWxsOyAxMC1WZXJ5IHJlcHJlc2VudGF0aXZlKlwNClZhcmlhYmxlOiBjb250aW51b3VzXA0KTWV0aG9kOiBBTk5PVkEgdGVzdCBvciBLVyB0ZXN0IChkZXBlbmRzIG9uIHdoZXRoZXIgaXQncyBub3JtYWxseSBkaXN0cmlidXRlZClcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4qKg0KYGBge3J9DQojIGNvbWJpbmUgZGF0YSBmcm9tIGRpZmZlcmVudCBncm91cHMNCnN1cnZleV9xMjkgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTI5X2xpc3QgPC0gbGlzdCgiUTQuMjlfMSIsIlE2LjI5XzEiLCAiUTguMjlfMSIsICJRMTAuMjlfMSIsICJRMTIuMjlfMSIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3EyOV9saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygicTI5X3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X3EyOSA8LSByYmluZChzdXJ2ZXlfcTI5LCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X3EyOSRxMjlfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfcTI5JHEyOV92YWx1ZSkNCmBgYA0KDQpTdGF0aXN0aWNhbCB0ZXN0DQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0KIyBzdW1tYXJ5KHN1cnZleV9xMjkkcTI5X3ZhbHVlKQ0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X3EyOSRxMjlfdmFsdWUpDQojIHJ1biBLcnVza2FsLVdhbGxpcyB0ZXN0DQprcnVza2FsX3Rlc3QgPC0ga3J1c2thbC50ZXN0KHEyOV92YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X3EyOSkNCnByaW50KGtydXNrYWxfdGVzdCkNCmBgYA0KU3VtbWFyeSBzdGF0aXN0aWNzDQpgYGB7cn0NCiMgU3VtbWFyeSBzdGF0aXN0aWNzDQpzdXJ2ZXlfcTI5X3N1bW1hcnkgPC0gc3VydmV5X3EyOSAlPiUNCiAgZ3JvdXBfYnkoZ3JvdXApICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbiA9IG1lYW4ocTI5X3ZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgIG1lZGlhbiA9IG1lZGlhbihxMjlfdmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgc2QgPSBzZChxMjlfdmFsdWUsIG5hLnJtID0gVFJVRSkNCiAgKQ0KYGBgDQpQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQojIEdyb3VwZWQgYmFyLXN0eWxlIGhpc3RvZ3JhbQ0KZ2dwbG90KHN1cnZleV9xMjksIGFlcyh4ID0gZmFjdG9yKHEyOV92YWx1ZSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMjkgVGhlIGRpc3RyaWJ1dGlvbiBvZiByZXByZXNlbnRhdGl2ZW5lc3Mgb2YgdGhlIHVuY2VydGFpbnR5IGJ5IGdyb3VwIiwNCiAgICB4ID0gIlF4eC4yOSBSZXNwb25zZSIsDQogICAgeSA9ICJDb3VudCIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjICEgUXh4LjMwIFJlYWRhYmlsaXR5IG9mIHRoZSBGb3JlY2FzdA0KT24gYSBzY2FsZSBvZiAxIHRvIDEwLCB3aGVyZSAxIG1lYW5zIHZlcnkgZGlmZmljdWx0IGFuZCAxMCBtZWFucyB2ZXJ5IGVhc3ksIGhvdyBlYXN5IG9yIGRpZmZpY3VsdCBkbyB5b3UgZmluZCB0aGUgZ3JhcGggdG8gdW5kZXJzdGFuZD9cDQoqMS1WZXJ5IGRpZmZpY3VsdDsgMTAtVmVyeSBlYXN5KlwNClZhcmlhYmxlOiBjb250aW51b3VzXA0KTWV0aG9kOiBBTk5PVkEgdGVzdCBvciBLVyB0ZXN0IChkZXBlbmRzIG9uIHdoZXRoZXIgaXQncyBub3JtYWxseSBkaXN0cmlidXRlZClcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gVGhlcmUgYXJlIHN0YXRpc3RpY2FsIGRpZmZlcmVuY2UgYmV0d2VlbiBjb250cm9sIGdyb3VwIHZzLiBmYW4gY2hhcnQgc2xpY2UgZ3JvdXA7IGNvbnRyb2wgZ3JvdXAgdnMuIGJlbGwgY3VydmU7IGVycm9yIGJhciBncm91cCB2cy4gYmVsbCBjdXJ2ZSBncm91cC4qKg0KYGBge3J9DQojIGNvbWJpbmUgZGF0YSBmcm9tIGRpZmZlcmVudCBncm91cHMNCnN1cnZleV9xMzAgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfcTMwX2xpc3QgPC0gbGlzdCgiUTQuMzBfMSIsIlE2LjMwXzEiLCAiUTguMzBfMSIsICJRMTAuMzBfMSIsICJRMTIuMzBfMSIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3EzMF9saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygicTMwX3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X3EzMCA8LSByYmluZChzdXJ2ZXlfcTMwLCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X3EzMCRxMzBfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfcTMwJHEzMF92YWx1ZSkNCmBgYA0KDQpTdGF0aXN0aWNhbCB0ZXN0DQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0KIyBzdW1tYXJ5KHN1cnZleV9xMzAkcTMwX3ZhbHVlKQ0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X3EzMCRxMzBfdmFsdWUpDQojIHJ1biBLcnVza2FsLVdhbGxpcyB0ZXN0DQprcnVza2FsX3Rlc3QgPC0ga3J1c2thbC50ZXN0KHEzMF92YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X3EzMCkNCnByaW50KGtydXNrYWxfdGVzdCkNCiMgUG9zdC1ob2MgdGVzdA0KZHVublRlc3QocTMwX3ZhbHVlIH4gZ3JvdXAsIGRhdGEgPSBzdXJ2ZXlfcTMwLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQpgYGANClN1bW1hcnkgc3RhdGlzdGljcw0KYGBge3J9DQojIFN1bW1hcnkgc3RhdGlzdGljcw0Kc3VydmV5X3EzMF9zdW1tYXJ5IDwtIHN1cnZleV9xMzAgJT4lDQogIGdyb3VwX2J5KGdyb3VwKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW4gPSBtZWFuKHEzMF92YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBtZWRpYW4gPSBtZWRpYW4ocTMwX3ZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgIHNkID0gc2QocTMwX3ZhbHVlLCBuYS5ybSA9IFRSVUUpDQogICkNCmBgYA0KDQpQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQojIEdyb3VwZWQgYmFyLXN0eWxlIGhpc3RvZ3JhbQ0KZ2dwbG90KHN1cnZleV9xMzAsIGFlcyh4ID0gZmFjdG9yKHEzMF92YWx1ZSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMzAgVGhlIGRpc3RyaWJ1dGlvbiBvZiByZWFkYWJpbGl0eSBvZiB0aGUgZm9yZWNhc3QgYnkgZ3JvdXAiLA0KICAgIHggPSAiUXh4LjMwIFJlc3BvbnNlIiwNCiAgICB5ID0gIkNvdW50IiwNCiAgICBmaWxsID0gIkdyb3VwIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCiMjIFF4eC4zMSBUcnVzdCBvZiB0aGUgRm9yZWNhc3QNCk9uIGEgc2NhbGUgb2YgMSB0byAxMCwgd2hlcmUgMSBtZWFucyB5b3UgZG9u4oCZdCB0cnVzdCB0aGUgaW5mbGF0aW9uIGZvcmVjYXN0IGF0IGFsbCBhbmQgMTAgbWVhbnMgeW91IGZ1bGx5IHRydXN0IGl0LCBob3cgbXVjaCBkbyB5b3UgdHJ1c3QgdGhlIGluZmxhdGlvbiBmb3JlY2FzdCBzaG93biBpbiB0aGUgZ3JhcGg/XA0KKjEtRG9uJ3QgdHJ1c3QgYXQgYWxsOyAxMC1GdWxseSB0cnVzdCpcDQpWYXJpYWJsZTogY29udGludW91c1wNCk1ldGhvZDogQU5OT1ZBIHRlc3Qgb3IgS1cgdGVzdCAoZGVwZW5kcyBvbiB3aGV0aGVyIGl0J3Mgbm9ybWFsbHkgZGlzdHJpYnV0ZWQpXA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuICoqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3EzMSA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMzFfbGlzdCA8LSBsaXN0KCJRNC4zMV8xIiwiUTYuMzFfMSIsICJROC4zMV8xIiwgIlExMC4zMV8xIiwgIlExMi4zMV8xIikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTMxX2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxMzFfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTMxIDwtIHJiaW5kKHN1cnZleV9xMzEsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTMxJHEzMV92YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xMzEkcTMxX3ZhbHVlKQ0KYGBgDQoNClN0YXRpc3RpY2FsIHRlc3QNCmBgYHtyfQ0KIyBJbml0aWFsIENoZWNrDQojIHN1bW1hcnkoc3VydmV5X3EzMSRxMzFfdmFsdWUpDQoNCiMgY2hlY2sgbm9ybWFsaXR5IC0tPiB0aGUgZGF0YSBpcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQNCiMgc2hhcGlyby50ZXN0KHN1cnZleV9xMzEkcTMxX3ZhbHVlKQ0KDQojIHJ1biBLcnVza2FsLVdhbGxpcyB0ZXN0DQprcnVza2FsX3Rlc3QgPC0ga3J1c2thbC50ZXN0KHEzMV92YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X3EzMSkNCnByaW50KGtydXNrYWxfdGVzdCkNCmBgYA0KU3VtbWFyeSBzdGF0aXN0aWNzDQpgYGB7cn0NCiMgU3VtbWFyeSBzdGF0aXN0aWNzDQpzdXJ2ZXlfcTMxX3N1bW1hcnkgPC0gc3VydmV5X3EzMSAlPiUNCiAgZ3JvdXBfYnkoZ3JvdXApICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbiA9IG1lYW4ocTMxX3ZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgIG1lZGlhbiA9IG1lZGlhbihxMzFfdmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgc2QgPSBzZChxMzFfdmFsdWUsIG5hLnJtID0gVFJVRSkNCiAgKQ0KYGBgDQoNClBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgR3JvdXBlZCBiYXItc3R5bGUgaGlzdG9ncmFtDQpnZ3Bsb3Qoc3VydmV5X3EzMSwgYWVzKHggPSBmYWN0b3IocTMxX3ZhbHVlKSwgZmlsbCA9IGZhY3Rvcihncm91cCkpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlF4eC4zMSBUaGUgZGlzdHJpYnV0aW9uIG9mIHRydXN0IG9mIHRoZSBmb3JlY2FzdCBieSBncm91cCIsDQogICAgeCA9ICJReHguMzEgUmVzcG9uc2UiLA0KICAgIHkgPSAiQ291bnQiLA0KICAgIGZpbGwgPSAiR3JvdXAiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyBTa2V3ZWQgRGF0YSA8YSBuYW1lPSJza2V3ZWQtZGF0YSI+PC9hPg0KIyMgUXh4LjMzIFByb2JhYmlsaXR5IG9mIGhpZ2hlciB0aGFuIDMlDQpCYXNlZCBvbiB0aGUgaW5mbGF0aW9uIGZvcmVjYXN0IHByb3ZpZGVkLCB3aGF0IGRvIHlvdSB0aGluayBpcyB0aGUgcHJvYmFiaWxpdHkgb2YgaW5mbGF0aW9uIGVuZGluZyB1cCBoaWdoZXIgdGhhbiAzJT9cDQpEZWZpbml0aXZlIENvcnJlY3QgQW5zd2VyIC0gNVwNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgJiBwcm9wb3J0aW9uIHRlc3RcDQoqKlJlc3VsdDogVGhlcmUgaXMgbm8gc3RhdGlzdGljYWwgZGlmZmVyZW5jZSBhY3Jvc3MgZGlmZmVyZW50IGdyb3VwcyBhbmQgdGhlIGxhcmdlc3QgcHJvcG9ydGlvbiBvZiBwYXJ0aWNpcGFudHMgY2FuIHVuZGVyc3RhbmQgdGhlIHByb2JhYmlsaXR5IGNvcnJlY3RseSwgYnV0IG9ubHkgYWNjb3VudCBmb3IgMjglIG9mIHRoZSBlbnRpcmUgcmVzcG9uZGVudHMuICoqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X3EzMyA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9xMzNfbGlzdCA8LSBsaXN0KCJRNi4zMyIsIlE4LjMzIiwgIlExMC4zMyIsICJRMTIuMzMiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhza2V3ZWRfZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gc2tld2VkX2dyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X3EzM19saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygicTMzX3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X3EzMyA8LSByYmluZChzdXJ2ZXlfcTMzLCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X3EzMyRxMzNfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfcTMzJHEzM192YWx1ZSkNCmBgYA0KDQpUZXN0IHRoZSBwcm9wb3J0aW9uIG9mIGNvcnJlY3QgYW5zd2VyDQpgYGB7cn0NCnN1cnZleV9xMzNfY29udGluZ2VuY3kgPC0gdGFibGUoc3VydmV5X3EzMyRxMzNfdmFsdWUsIHN1cnZleV9xMzMkZ3JvdXApDQpwcmludChzdXJ2ZXlfcTMzX2NvbnRpbmdlbmN5KQ0Kc3VydmV5X3EzM19jb3JyZWN0IDwtIHN1cnZleV9xMzNfY29udGluZ2VuY3lbNSxdDQpzdXJ2ZXlfcTMzX2dyb3VwX3RvdGFsIDwtIGNvbFN1bXMoc3VydmV5X3EzM19jb250aW5nZW5jeSkNCnByb3AudGVzdChzdXJ2ZXlfcTMzX2NvcnJlY3QsIHN1cnZleV9xMzNfZ3JvdXBfdG90YWwpDQpgYGANClBsb3QgcHJvYmFiaWxpdHkgb2YgaGlnaGVyIHRoYW4gMyUgKHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMpDQpgYGB7cn0NCnN1cnZleV9xMzNfcHJvcCAgPC0gYXMuZGF0YS5mcmFtZShzdXJ2ZXlfcTMzX2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMoc3VydmV5X3EzM19wcm9wKSA8LSBjKCJReHguMzMiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnN1cnZleV9xMzNfcHJvcCA8LSBzdXJ2ZXlfcTMzX3Byb3AgJT4lDQogIG11dGF0ZShReHguMzNfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgUXh4LjMzID09ICIxIiB+ICIxLU1vcmUgdGhhbiA2MCUiLA0KICAgIFF4eC4zMyA9PSAiMiIgfiAiMy00MC01MCUiLA0KICAgIFF4eC4zMyA9PSAiMyIgfiAiNC0zMC00MCUiLA0KICAgIFF4eC4zMyA9PSAiNCIgfiAiNS1MZXNzIHRoYW4gMzAlIiwNCiAgICBReHguMzMgPT0gIjUiIH4gIjItNTAtNjAlIg0KICApKQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnN1cnZleV9xMzNfcHJvcCA8LSBzdXJ2ZXlfcTMzX3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3Qoc3VydmV5X3EzM19wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUXh4LjMzX2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofkdyb3VwKSsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMzMgQW5zd2VyIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgdGhlIGhpc3RvZ3JhbSBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQojIGZvcmNlIG9yZGVyIGZvciBncmFwaA0Kc3VydmV5X3EzMyA8LSBzdXJ2ZXlfcTMzICU+JQ0KICBtdXRhdGUoDQogICAgcTMzX3ZhbHVlX3JlID0gZmFjdG9yKA0KICAgICAgcTMzX3ZhbHVlLA0KICAgICAgbGV2ZWxzID0gYygxLCA1LCAyLCAzLCA0KQ0KICAgICkNCiAgKQ0KIyBoaXN0b2dyYW0gaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmdncGxvdChzdXJ2ZXlfcTMzLCBhZXMoeCA9IHEzM192YWx1ZV9yZSkpICsNCiAgZ2VvbV9iYXIoZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMzMgUmVzcG9uc2VzIChmb3JjZWQgMS01LTItMy00IG9yZGVyKSIsDQogICAgeCAgICAgPSAiUXh4LjMzIiwNCiAgICB5ICAgICA9ICJDb3VudCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCiMjIFF4eC4zNCBTZWxmLXJlcG9ydGVkIGxpa2VsaWhvb2Qgb2YgaW5mbGF0aW9uIGJlaW5nIGhpZ2hlciB0aGFuIDMlDQpIb3cgbGlrZWx5IGRvIHlvdSB0aGluayBpdCBpcyB0aGF0IHRoZSBpbmZsYXRpb24gd2lsbCBiZSBoaWdoZXIgdGhhbiAzJT9cDQoqYXNjZW5kaW5nIHZhbHVlLWluY3JlYXNpbmcgbGlrZWxpaG9vZCpcDQpWYXJpYWJsZTogdHJlYXQgYXMgY29udGludW91c1wNCk1ldGhvZDogS3J1c2thbC1XYWxsaXMgdGVzdFwNCioqUmVzdWx0OiBGYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGUgbWFqb3JpdHkgb2YgcmVzcG9uZGVudHMgdGhpbmsgaXQncyBxdWl0ZSBsaWtlbHkuKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfcTM0IDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X3EzNF9saXN0IDwtIGxpc3QoIlE2LjM0XzEiLCJROC4zNF8xIiwgIlExMC4zNF8xIiwgIlExMi4zNF8xIikNCmZvciAoaSBpbiBzZXFfYWxvbmcoc2tld2VkX2dyb3VwX2xpc3QpKSB7DQogIGRmIDwtIHNrZXdlZF9ncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9xMzRfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoInEzNF92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9xMzQgPC0gcmJpbmQoc3VydmV5X3EzNCwgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9xMzQkcTM0X3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X3EzNCRxMzRfdmFsdWUpDQpgYGANCktXIHRlc3QNCmBgYHtyfQ0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X3EzNCRxMzRfdmFsdWUpDQoNCiMgcnVuIEtydXNrYWwtV2FsbGlzIHRlc3QNCmtydXNrYWxfdGVzdCA8LSBrcnVza2FsLnRlc3QocTM0X3ZhbHVlIH4gZ3JvdXAsIGRhdGEgPSBzdXJ2ZXlfcTM0KQ0KcHJpbnQoa3J1c2thbF90ZXN0KQ0KYGBgDQpQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQojIEdyb3VwZWQgYmFyLXN0eWxlIGhpc3RvZ3JhbQ0KZ2dwbG90KHN1cnZleV9xMzQsIGFlcyh4ID0gZmFjdG9yKHEzNF92YWx1ZSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgIyBhZGQgbGFiZWxzDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWxpa2VsaWhvb2RfbGFiZWxzKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUXh4LjM0IFNlbGYtcmVwb3J0ZWQgbGlrZWxpaG9vZCBvZiBpbmZsYXRpb24gYmVpbmcgaGlnaGVyIHRoYW4gMyUgZGlzdHJpYnV0aW9uIGJ5IGdyb3VwIiwNCiAgICB4ID0gIlF4eC4zNCBSZXNwb25zZSIsDQogICAgeSA9ICJDb3VudCIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgYmFyIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X3EzNCwgYWVzKHggPSBxMzRfdmFsdWUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicyh0aXRsZSA9ICJReHguMzQgU2VsZi1yZXBvcnRlZCBsaWtlbGlob29kIG9mIGluZmxhdGlvbiBiZWluZyBoaWdoZXIgdGhhbiAzJSBkaXN0cmlidXRpb24iLA0KICAgICAgIHggPSAiUXh4LjM0IiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMubnVtZXJpYyhuYW1lcyhsaWtlbGlob29kX2xhYmVscykpLCANCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxpa2VsaWhvb2RfbGFiZWxzKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCiMjIFF4eC4zNiBEZXZpYXRpb24gZnJvbSBjZW50cmFsIGVzdGltYXRlDQpCYXNlZCBvbiB0aGUgaW5mbGF0aW9uIGZvcmVjYXN0IHByb3ZpZGVkLCAgZG8geW91IHRoaW5rIHRoZXJlIGlzIGEgaGlnaGVyIHJpc2sgb2YgaW5mbGF0aW9uIGV4Y2VlZGluZyB0aGUgY2VudHJhbCBlc3RpbWF0ZSBvciBvZiBiZWluZyBsZXNzIHRoYW4gdGhpcyBjZW50cmFsIGVzdGltYXRlP1wNCkRlZmluaXRpdmUgQ29ycmVjdCBBbnN3ZXIgLSAxXA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSAmIHByb3BvcnRpb24gdGVzdFwNCioqUmVzdWx0OiBUaGVyZSBpcyBubyBzdGF0aXN0aWNhbCBkaWZmZXJlbmNlIGFjcm9zcyBncm91cC4gNjglIG9mIHJlc3BvbmRlbnRzIGNhbiB1bmRlcnN0YW5kIHRoZXJlIGlzIGJpZ2dlciB1cHNpZGUgcmlzay4gKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfcTM2IDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X3EzNl9saXN0IDwtIGxpc3QoIlE2LjM2IiwiUTguMzYiLCAiUTEwLjM2IiwgIlExMi4zNiIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKHNrZXdlZF9ncm91cF9saXN0KSkgew0KICBkZiA8LSBza2V3ZWRfZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTM2X2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxMzZfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTM2IDwtIHJiaW5kKHN1cnZleV9xMzYsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTM2JHEzNl92YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xMzYkcTM2X3ZhbHVlKQ0KYGBgDQoNCkNvbnRpbmdlbmN5IHRhYmxlDQpgYGB7cn0NCnN1cnZleV9xMzZfY29udGluZ2VuY3kgPC0gdGFibGUoc3VydmV5X3EzNiRxMzZfdmFsdWUsIHN1cnZleV9xMzYkZ3JvdXApDQpwcmludChzdXJ2ZXlfcTM2X2NvbnRpbmdlbmN5KQ0KY2hpc3FfcmVzdWx0IDwtIGNoaXNxLnRlc3Qoc3VydmV5X3EzNl9jb250aW5nZW5jeSkNCnByaW50KGNoaXNxX3Jlc3VsdCkNCmBgYA0KVGVzdCB0aGUgcHJvcG9ydGlvbiBvZiBjb3JyZWN0IGFuc3dlcg0KYGBge3J9DQpzdXJ2ZXlfcTM2X2NvcnJlY3QgPC0gc3VydmV5X3EzNl9jb250aW5nZW5jeVsxLF0NCnN1cnZleV9xMzZfZ3JvdXBfdG90YWwgPC0gY29sU3VtcyhzdXJ2ZXlfcTM2X2NvbnRpbmdlbmN5KQ0KcHJvcC50ZXN0KHN1cnZleV9xMzZfY29ycmVjdCwgc3VydmV5X3EzNl9ncm91cF90b3RhbCkNCmBgYA0KDQpQbG90IHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0Kc3VydmV5X3EzNl9wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHN1cnZleV9xMzZfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhzdXJ2ZXlfcTM2X3Byb3ApIDwtIGMoIlF4eC4zNiIsICJHcm91cCIsICJDb3VudCIpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0Kc3VydmV5X3EzNl9wcm9wIDwtIHN1cnZleV9xMzZfcHJvcCAlPiUNCiAgbXV0YXRlKFF4eC4zNl9sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBReHguMzYgPT0gIjEiIH4gIjEtYmlnZ2VyIHVwc2lkZSByaXNrIiwNCiAgICBReHguMzYgPT0gIjIiIH4gIjItYmlnZ2VyIGRvd25zaWRlIHJpc2siLA0KICAgIFF4eC4zNiA9PSAiMyIgfiAiMy1lcXVhbCByaXNrcyBvbiBib3RoIHNpZGVzIg0KICApKQ0KIyBjYWxjdWxhdGUgcHJvcG9ydGlvbnMgd2l0aGluIGVhY2ggZ3JvdXANCnN1cnZleV9xMzZfcHJvcCA8LSBzdXJ2ZXlfcTM2X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3Qoc3VydmV5X3EzNl9wcm9wLCBhZXMoeCA9IGFzLmZhY3RvcihgUXh4LjM2X2xhYmVsYCksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gR3JvdXApKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofkdyb3VwKSsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJReHguMzYgQW5zd2VyIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANCg0KUGxvdCB0aGUgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X3EzNiwgYWVzKHggPSBxMzZfdmFsdWUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicyh0aXRsZSA9ICJReHguMzYgQW5zd2VyIEJhciBDaGFydCIsDQogICAgICAgeCA9ICJReHguMzYiLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHN1cnZleV9xMzYkcTM2X3ZhbHVlLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjID8gUXh4LjM3IFJpc2sgb2YgZW5kaW5nIG91dHNpZGUNCklmIHRoZSBhY3R1YWwgaW5mbGF0aW9uIGVuZHMgdXAgb3V0c2lkZSB0aGUgYmxhY2sgbGluZSwgd2hpY2ggc2lkZSBpcyBtb3JlIGxpa2VseSwgYmFzZWQgb24gdGhlIHVuY2VydGFpbnR5IGRlcGljdGVkIGluIHRoZSBncmFwaD9cDQpEZWZpbml0aXZlIENvcnJlY3QgQW5zd2VyIC0gMVwNClZhcmlhYmxlOiBjYXRlZ29yaWNhbFwNCk1ldGhvZDogY29udGluZ2VuY3kgdGFibGUgJiBwcm9wb3J0aW9uIHRlc3RcDQoqKlJlc3VsdDogNjMlIHJlc3BvbmRlbnRzIHRoaW5rIGlmIHRoZSBhY3R1YWwgaW5mbGF0aW9uIGVuZHMgdXAgb3V0c2lkZSwgaXQncyBtb3JlIGxpa2VseSB0byBiZSBvbiB0aGUgdXBwZXIgc2lkZS4gKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfcTM3IDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X3EzN19saXN0IDwtIGxpc3QoIlE2LjM3IiwiUTguMzciLCAiUTEwLjM3IiwgIlExMi4zNyIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKHNrZXdlZF9ncm91cF9saXN0KSkgew0KICBkZiA8LSBza2V3ZWRfZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfcTM3X2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJxMzdfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfcTM3IDwtIHJiaW5kKHN1cnZleV9xMzcsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfcTM3JHEzN192YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9xMzckcTM3X3ZhbHVlKQ0KYGBgDQoNCkNvbnRpbmdlbmN5IHRhYmxlDQpgYGB7cn0NCnN1cnZleV9xMzdfY29udGluZ2VuY3kgPC0gdGFibGUoc3VydmV5X3EzNyRxMzdfdmFsdWUsIHN1cnZleV9xMzckZ3JvdXApDQpwcmludChzdXJ2ZXlfcTM3X2NvbnRpbmdlbmN5KQ0KDQojIGNoaXNxX3Jlc3VsdCA8LSBjaGlzcS50ZXN0KHN1cnZleV9xMzdfY29udGluZ2VuY3kpDQojIHByaW50KGNoaXNxX3Jlc3VsdCkNCg0KIyBUZXN0IHRoZSBwcm9wb3J0aW9uIG9mIGNvcnJlY3QgYW5zd2VyDQpzdXJ2ZXlfcTM3X2NvcnJlY3QgPC0gc3VydmV5X3EzN19jb250aW5nZW5jeVsxLF0NCnN1cnZleV9xMzdfZ3JvdXBfdG90YWwgPC0gY29sU3VtcyhzdXJ2ZXlfcTM3X2NvbnRpbmdlbmN5KQ0KcHJvcC50ZXN0KHN1cnZleV9xMzdfY29ycmVjdCwgc3VydmV5X3EzN19ncm91cF90b3RhbCkNCg0KIyBwYWlyd2lzZSBwcm9wb3J0aW9uIHRlc3QNCnBhaXJ3aXNlLnByb3AudGVzdCgNCiAgeCA9IHN1cnZleV9xMzdfY29udGluZ2VuY3lbMSxdLA0KICBuID0gY29sU3VtcyhzdXJ2ZXlfcTM3X2NvbnRpbmdlbmN5KSwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiICMgb3IgImhvbG0iLCAiQkgiDQopDQpgYGANClBsb3QgcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQpzdXJ2ZXlfcTM3X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUoc3VydmV5X3EzN19jb250aW5nZW5jeSkNCiMgcmVuYW1lIGNvbHVtbnMNCm5hbWVzKHN1cnZleV9xMzdfcHJvcCkgPC0gYygiUXh4LjM3IiwgIkdyb3VwIiwgIkNvdW50IikNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpzdXJ2ZXlfcTM3X3Byb3AgPC0gc3VydmV5X3EzN19wcm9wICU+JQ0KICBtdXRhdGUoUXh4LjM3X2xhYmVsID0gY2FzZV93aGVuKA0KICAgIFF4eC4zNyA9PSAiMSIgfiAiMS1Nb3JlIGxpa2VseSB0byBiZSBvbiB0aGUgdXBwZXIgc2lkZSIsDQogICAgUXh4LjM3ID09ICIyIiB+ICIyLU1vcmUgbGlrZWx5IHRvIGJlIG9uIHRoZSBsb3dlciBzaWRlIiwNCiAgICBReHguMzcgPT0gIjMiIH4gIjMtRXF1YWwgY2hhbmNlcyBvZiBiZWluZyBvbiBlaXRoZXIgc2lkZSINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpzdXJ2ZXlfcTM3X3Byb3AgPC0gc3VydmV5X3EzN19wcm9wICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gQ291bnQgLyBzdW0oQ291bnQpKQ0KZ2dwbG90KHN1cnZleV9xMzdfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYFF4eC4zN19sYWJlbGApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IEdyb3VwKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH5Hcm91cCkrDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUXh4LjM3IEFuc3dlciBQcm9wb3Rpb24gUGxvdCBhY3Jvc3MgR3JvdXBzIiwNCiAgICB4ID0gIlJlc3BvbnNlIiwNCiAgICB5ID0gIlByb3BvcnRpb24iDQogICkgKw0KICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQpQbG90IHRoZSBoaXN0b2dyYW0gaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmBgYHtyfQ0KIyBoaXN0b2dyYW0gaW5jbHVkaW5nIGFsbCBwYXJ0aWNpcGFudHMNCmdncGxvdChzdXJ2ZXlfcTM3LCBhZXMoeCA9IHEzN192YWx1ZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICBsYWJzKHRpdGxlID0gIlF4eC4zNyBBbnN3ZXIgQmFyIENoYXJ0IiwNCiAgICAgICB4ID0gIlF4eC4zNyIsDQogICAgICAgeSA9ICJDb3VudCIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCBtYXgoc3VydmV5X3EzNyRxMzdfdmFsdWUsIG5hLnJtID0gVFJVRSksIGJ5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQoNCg0KIyBEZWNpc2lvbi1tYWtpbmcgPGEgbmFtZT0iZGVjaXNpb24tbWFraW5nIj48L2E+DQojIyBELjMgSW52ZXN0bWVudCBEZWNpc2lvbg0KV2hpY2ggYm9uZCB3b3VsZCB5b3UgY2hvb3NlIHRvIGludmVzdCBpbj9cDQpWYXJpYWJsZTogY2F0ZWdvcmljYWxcDQpNZXRob2Q6IGNvbnRpbmdlbmN5IHRhYmxlICYgcHJvcG9ydGlvbiB0ZXN0XA0KKipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuICoqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X2QzIDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X2QzX2xpc3QgPC0gbGlzdCgiUTUuMyIsIlE3LjMiLCAiUTkuMyIsICJRMTEuMyIsICJRMTMuMyIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X2QzX2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJkM192YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9kMyA8LSByYmluZChzdXJ2ZXlfZDMsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfZDMkZDNfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfZDMkZDNfdmFsdWUpDQpgYGANCkNvbnRpbmdlbmN5IHRhYmxlDQpgYGB7cn0NCnN1cnZleV9kM19jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfZDMkZDNfdmFsdWUsIHN1cnZleV9kMyRncm91cCkNCnByaW50KHN1cnZleV9kM19jb250aW5nZW5jeSkNCiMgY2hpLXNxdWFyZWQgdGVzdA0KY2hpc3EudGVzdChzdXJ2ZXlfZDNfY29udGluZ2VuY3kpDQoNCmBgYA0KUGxvdCBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnN1cnZleV9kM19wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHN1cnZleV9kM19jb250aW5nZW5jeSkNCiMgcmVuYW1lIGNvbHVtbnMNCm5hbWVzKHN1cnZleV9kM19wcm9wKSA8LSBjKCJELjMiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnN1cnZleV9kM19wcm9wIDwtIHN1cnZleV9kM19wcm9wICU+JQ0KICBtdXRhdGUoRC4zX2xhYmVsID0gY2FzZV93aGVuKA0KICAgIEQuMyA9PSAiMSIgfiAiQS4gTm9taW5hbCBCb25kIiwNCiAgICBELjMgPT0gIjIiIH4gIkIuIEluZmxhdGlvbi1Qcm90ZWN0ZWQgQm9uZCINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpzdXJ2ZXlfZDNfcHJvcCA8LSBzdXJ2ZXlfZDNfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoR3JvdXApICU+JQ0KICBtdXRhdGUoUHJvcG9ydGlvbiA9IENvdW50IC8gc3VtKENvdW50KSkNCmdncGxvdChzdXJ2ZXlfZDNfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYEQuM19sYWJlbGApLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IEdyb3VwKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH5Hcm91cCkrDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRC4zIEFuc3dlciBQcm9wb3Rpb24gUGxvdCBhY3Jvc3MgR3JvdXBzIiwNCiAgICB4ID0gIlJlc3BvbnNlIiwNCiAgICB5ID0gIlByb3BvcnRpb24iDQogICkgKw0KICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KYGBgDQpQbG90IHBpZSBjaGFydCBpbmNsdWRpbmcgYWxsIHBhcnRpY2lwYW50cw0KYGBge3J9DQpzdXJ2ZXlfZDNfc3VtbWFyeSA8LSBzdXJ2ZXlfZDNfcHJvcCAlPiUNCiAgZ3JvdXBfYnkoYEQuM19sYWJlbGApICU+JQ0KICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oQ291bnQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgbXV0YXRlKHByb3BvcnRpb24gPSB0b3RhbF9jb3VudCAvIHN1bSh0b3RhbF9jb3VudCksDQogICAgICAgICBgRC4zX2dyYXBoX2xhYmVsYCA9IHBhc3RlMChgRC4zX2xhYmVsYCwgIiAoIiwgcm91bmQocHJvcG9ydGlvbiAqIDEwMCwgMiksICIgJSkiKSkNCmdncGxvdChzdXJ2ZXlfZDNfc3VtbWFyeSwgYWVzKHggPSAiIix5ID0gcHJvcG9ydGlvbiwgZmlsbCA9IGBELjNfZ3JhcGhfbGFiZWxgKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgbGFicyh0aXRsZSA9ICJELjMgSW52ZXN0bWVudCBEZWNpc2lvbiBTdW1tYXJ5IFBpZSBDaGFydCIsDQogICAgICAgeCA9ICIiLA0KICAgICAgIHkgPSAiIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkNCmBgYA0KIyMgRC40IENvbmZpZGVuY2UgaW4gZGVjaXNpb24tbWFraW5nDQpPbiBhIHNjYWxlIG9mIDEgdG8gMTAsIHdoZXJlIDEgbWVhbnMgbm90IGNvbmZpZGVudCBhdCBhbGwgYW5kIDEwIG1lYW5zIHZlcnkgY29uZmlkZW50LCBob3cgY29uZmlkZW50ICBhcmUgeW91IGluIG1ha2luZyB0aGUgZGVjaXNpb24/XA0KKjEtTm90IGNvbmZpZGVudCBhdCBhbGw7IDEwLVZlcnkgY29uZmlkZW50KlwNClZhcmlhYmxlOiBjb250aW51b3VzXA0KTWV0aG9kOiBBTk5PVkEgdGVzdCBvciBLVyB0ZXN0IChkZXBlbmRzIG9uIHdoZXRoZXIgaXQncyBub3JtYWxseSBkaXN0cmlidXRlZClcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfZDQgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfZDRfbGlzdCA8LSBsaXN0KCJRNS40XzEiLCJRNy40XzEiLCAiUTkuNF8xIiwgIlExMS40XzEiLCAiUTEzLjRfMSIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X2Q0X2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJkNF92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9kNCA8LSByYmluZChzdXJ2ZXlfZDQsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfZDQkZDRfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfZDQkZDRfdmFsdWUpDQpgYGANClN0YXRpc3RpY2FsIHRlc3QNCmBgYHtyfQ0KIyBJbml0aWFsIENoZWNrDQojIHN1bW1hcnkoc3VydmV5X2Q0JGQ0X3ZhbHVlKQ0KIyBjaGVjayBub3JtYWxpdHkgLS0+IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZA0KIyBzaGFwaXJvLnRlc3Qoc3VydmV5X2Q0JGQ0X3ZhbHVlKQ0KDQojIHJ1biBLcnVza2FsLVdhbGxpcyB0ZXN0DQprcnVza2FsX3Rlc3QgPC0ga3J1c2thbC50ZXN0KGQ0X3ZhbHVlIH4gZ3JvdXAsIGRhdGEgPSBzdXJ2ZXlfZDQpDQpwcmludChrcnVza2FsX3Rlc3QpDQpgYGANClN1bW1hcnkgc3RhdGlzdGljcw0KYGBge3J9DQojIFN1bW1hcnkgc3RhdGlzdGljcw0Kc3VydmV5X2Q0X3N1bW1hcnkgPC0gc3VydmV5X2Q0ICU+JQ0KICBncm91cF9ieShncm91cCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuID0gbWVhbihkNF92YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBtZWRpYW4gPSBtZWRpYW4oZDRfdmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgc2QgPSBzZChkNF92YWx1ZSwgbmEucm0gPSBUUlVFKQ0KICApDQpgYGANClBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCiMgR3JvdXBlZCBiYXItc3R5bGUgaGlzdG9ncmFtDQpnZ3Bsb3Qoc3VydmV5X2Q0LCBhZXMoeCA9IGZhY3RvcihkNF92YWx1ZSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJELjQgVGhlIGRpc3RyaWJ1dGlvbiBvZiBjb25maWRlbmNlIGluIGRlY2lzaW9uLW1ha2luZyBieSBncm91cCIsDQogICAgeCA9ICJELjQgUmVzcG9uc2UiLA0KICAgIHkgPSAiQ291bnQiLA0KICAgIGZpbGwgPSAiR3JvdXAiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMgRC42IENvbnNpZGVyaW5nIG5vbWluYWwgYm9uZA0KSWYgdGhlIHByb2JhYmlsaXR5IG9mIGluZmxhdGlvbiBiZWluZyBsb3cgKOKJpCAzJSkgaXMgZ3JlYXRlciB0aGFuIHRoZSBmb2xsb3dpbmcgcGVyY2VudGFnZXMsIEkgd291bGQgY29uc2lkZXIgaW52ZXN0aW5nIGluIHRoZSBub21pbmFsIGJvbmQ6XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSAmIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4qKg0KYGBge3J9DQojIGNvbWJpbmUgZGF0YSBmcm9tIGRpZmZlcmVudCBncm91cHMNCnN1cnZleV9kNiA8LSBkYXRhLmZyYW1lKCkNCnN1cnZleV9kNl9saXN0IDwtIGxpc3QoIlE1LjYiLCJRNy42IiwgIlE5LjYiLCAiUTExLjYiLCAiUTEzLjYiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9kNl9saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygiZDZfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfZDYgPC0gcmJpbmQoc3VydmV5X2Q2LCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X2Q2JGQ2X3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X2Q2JGQ2X3ZhbHVlKQ0KYGBgDQpDb250aW5nZW5jeSB0YWJsZQ0KYGBge3J9DQpzdXJ2ZXlfZDZfY29udGluZ2VuY3kgPC0gdGFibGUoc3VydmV5X2Q2JGQ2X3ZhbHVlLCBzdXJ2ZXlfZDYkZ3JvdXApDQpwcmludChzdXJ2ZXlfZDZfY29udGluZ2VuY3kpDQojIHJ1biBjaGktc3F1YXJlZCB0ZXN0DQpjaGlzcV9yZXN1bHQgPC0gY2hpc3EudGVzdChzdXJ2ZXlfZDZfY29udGluZ2VuY3kpDQpwcmludChjaGlzcV9yZXN1bHQpDQpgYGANClBsb3QgcHJvcG9ydGlvbiBiYXIgcGxvdCBhY3Jvc3MgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQpzdXJ2ZXlfZDZfcHJvcCAgPC0gYXMuZGF0YS5mcmFtZShzdXJ2ZXlfZDZfY29udGluZ2VuY3kpDQojIHJlbmFtZSBjb2x1bW5zDQpuYW1lcyhzdXJ2ZXlfZDZfcHJvcCkgPC0gYygiRC42IiwgIkdyb3VwIiwgIkNvdW50IikNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpzdXJ2ZXlfZDZfcHJvcCA8LSBzdXJ2ZXlfZDZfcHJvcCAlPiUNCiAgbXV0YXRlKEQuNl9sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBELjYgPT0gIjEiIH4gIjEtNDAlIiwNCiAgICBELjYgPT0gIjIiIH4gIjItNTAlIiwNCiAgICBELjYgPT0gIjMiIH4gIjMtNjAlIiwNCiAgICBELjYgPT0gIjQiIH4gIjQtZG8gbm90IHRoaW5rIGFib3V0IHByb2JhYmlsaXR5IiwNCiAgICBELjYgPT0gIjUiIH4gIjUtYWx3YXlzIGNob29zZSBhbiBpbmZsYXRpb24tcHJvdGVjdGVkIGJvbmQiLA0KICAgIEQuNiA9PSAiNyIgfiAiNi03MCUiLA0KICAgIEQuNiA9PSAiOCIgfiAiNy04MCUiDQogICkpDQojIGNhbGN1bGF0ZSBwcm9wb3J0aW9ucyB3aXRoaW4gZWFjaCBncm91cA0Kc3VydmV5X2Q2X3Byb3AgPC0gc3VydmV5X2Q2X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3Qoc3VydmV5X2Q2X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBELjZfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+R3JvdXApKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkQuNiBBbnN3ZXIgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KUGxvdCB0aGUgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X2Q2LCBhZXMoeCA9IGQ2X3ZhbHVlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogICMgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnModGl0bGUgPSAiRC42IEhpc3RvZ3JhbSIsDQogICAgICAgeCA9ICJELjYiLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHN1cnZleV9kNiRkNl92YWx1ZSwgbmEucm0gPSBUUlVFKSwgYnkgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMgRC43IENvbnNpZGVyaW5nIGluZmxhdGlvbi1wcm90ZWN0ZWQgYm9uZA0KSWYgdGhlIHByb2JhYmlsaXR5IG9mIGluZmxhdGlvbiBiZWluZyBoaWdoICg+IDMlKSBpcyBncmVhdGVyIHRoYW4gdGhlIGZvbGxvd2luZyBwZXJjZW50YWdlcywgSSB3b3VsZCBjb25zaWRlciBpbnZlc3RpbmcgaW4gdGhlIGluZmxhdGlvbi1wcm90ZWN0ZWQgYm9uZDpcDQpWYXJpYWJsZTogY2F0ZWdvcmljYWxcDQpNZXRob2Q6IGNvbnRpbmdlbmN5IHRhYmxlICYgY2hpLXNxdWFyZWQgdGVzdFwNCipSZXN1bHQ6IEZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfZDcgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfZDdfbGlzdCA8LSBsaXN0KCJRNS43IiwiUTcuNyIsICJROS43IiwgIlExMS43IiwgIlExMy43IikNCmZvciAoaSBpbiBzZXFfYWxvbmcoZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gZ3JvdXBfbGlzdFtbaV1dDQogIGNvbCA8LSBzdXJ2ZXlfZDdfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoImQ3X3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X2Q3IDwtIHJiaW5kKHN1cnZleV9kNywgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9kNyRkN192YWx1ZSA8LSBhcy5udW1lcmljKHN1cnZleV9kNyRkN192YWx1ZSkNCmBgYA0KQ29udGluZ2VuY3kgdGFibGUNCmBgYHtyfQ0Kc3VydmV5X2Q3X2NvbnRpbmdlbmN5IDwtIHRhYmxlKHN1cnZleV9kNyRkN192YWx1ZSwgc3VydmV5X2Q3JGdyb3VwKQ0KcHJpbnQoc3VydmV5X2Q3X2NvbnRpbmdlbmN5KQ0KIyBydW4gY2hpLXNxdWFyZWQgdGVzdA0KY2hpc3FfcmVzdWx0IDwtIGNoaXNxLnRlc3Qoc3VydmV5X2Q3X2NvbnRpbmdlbmN5KQ0KcHJpbnQoY2hpc3FfcmVzdWx0KQ0KYGBgDQpQbG90IHByb3BvcnRpb24gYmFyIHBsb3QgYWNyb3NzIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0Kc3VydmV5X2Q3X3Byb3AgIDwtIGFzLmRhdGEuZnJhbWUoc3VydmV5X2Q3X2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMoc3VydmV5X2Q3X3Byb3ApIDwtIGMoIkQuNyIsICJHcm91cCIsICJDb3VudCIpDQojIGFkZCBhIGxhYmVsbGVkIGNvbHVtbg0Kc3VydmV5X2Q3X3Byb3AgPC0gc3VydmV5X2Q3X3Byb3AgJT4lDQogIG11dGF0ZShELjdfbGFiZWwgPSBjYXNlX3doZW4oDQogICAgRC43ID09ICIxIiB+ICIxLTQwJSIsDQogICAgRC43ID09ICIyIiB+ICIyLTUwJSIsDQogICAgRC43ID09ICIzIiB+ICIzLTYwJSIsDQogICAgRC43ID09ICI0IiB+ICI0LWRvIG5vdCB0aGluayBhYm91dCBwcm9iYWJpbGl0eSIsDQogICAgRC43ID09ICI1IiB+ICI1LWFsd2F5cyBjaG9vc2UgYSBub21pbmFsIGJvbmQiLA0KICAgIEQuNyA9PSAiNyIgfiAiNi03MCUiLA0KICAgIEQuNyA9PSAiOCIgfiAiNy04MCUiDQogICkpDQojIGNhbGN1bGF0ZSBwcm9wb3J0aW9ucyB3aXRoaW4gZWFjaCBncm91cA0Kc3VydmV5X2Q3X3Byb3AgPC0gc3VydmV5X2Q3X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3Qoc3VydmV5X2Q3X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBELjdfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+R3JvdXApKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkQuNyBBbnN3ZXIgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KUGxvdCB0aGUgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X2Q3LCBhZXMoeCA9IGQ3X3ZhbHVlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogICMgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnModGl0bGUgPSAiRC43IEhpc3RvZ3JhbSIsDQogICAgICAgeCA9ICJELjciLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHN1cnZleV9kNyRkN192YWx1ZSwgbmEucm0gPSBUUlVFKSwgYnkgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMgRC44IEltcGFjdCBvbiBEZXNpY2lvbi1tYWtpbmcNCkNvbnNpZGVyaW5nIHRoZSBwYXlvZmYgZm9yIHRoZSBOb21pbmFsIEJvbmQsIHdoaWNoIG9mIHRoZSBmb2xsb3dpbmcgaGFzIGEgbGFyZ2VyIGltcGFjdCBvbiB5b3VyIGRlY2lzaW9uLW1ha2luZz9cDQpWYXJpYWJsZTogY2F0ZWdvcmljYWxcDQpNZXRob2Q6IGNvbnRpbmdlbmN5IHRhYmxlICYgY2hpLXNxdWFyZWQgdGVzdFwNCioqUmVzdWx0OiBGYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLioqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X2Q4IDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X2Q4X2xpc3QgPC0gbGlzdCgiUTUuOCIsIlE3LjgiLCAiUTkuOCIsICJRMTEuOCIsICJRMTMuOCIpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKGdyb3VwX2xpc3QpKSB7DQogIGRmIDwtIGdyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X2Q4X2xpc3RbW2ldXQ0KICB0ZW1wX3RhYmxlIDwtIGRmWywgYyhjb2wsICJncm91cCIpXQ0KICBuYW1lcyh0ZW1wX3RhYmxlKSA8LSBjKCJkOF92YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9kOCA8LSByYmluZChzdXJ2ZXlfZDgsIHRlbXBfdGFibGUpDQp9DQpzdXJ2ZXlfZDgkZDhfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfZDgkZDhfdmFsdWUpDQpgYGANCkNvbnRpbmdlbmN5IHRhYmxlDQpgYGB7cn0NCnN1cnZleV9kOF9jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfZDgkZDhfdmFsdWUsIHN1cnZleV9kOCRncm91cCkNCnByaW50KHN1cnZleV9kOF9jb250aW5nZW5jeSkNCiMgcnVuIGNoaS1zcXVhcmVkIHRlc3QNCmNoaXNxX3Jlc3VsdCA8LSBjaGlzcS50ZXN0KHN1cnZleV9kOF9jb250aW5nZW5jeSkNCnByaW50KGNoaXNxX3Jlc3VsdCkNCmBgYA0KUGxvdCBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnN1cnZleV9kOF9wcm9wICA8LSBhcy5kYXRhLmZyYW1lKHN1cnZleV9kOF9jb250aW5nZW5jeSkNCiMgcmVuYW1lIGNvbHVtbnMNCm5hbWVzKHN1cnZleV9kOF9wcm9wKSA8LSBjKCJELjgiLCAiR3JvdXAiLCAiQ291bnQiKQ0KIyBhZGQgYSBsYWJlbGxlZCBjb2x1bW4NCnN1cnZleV9kOF9wcm9wIDwtIHN1cnZleV9kOF9wcm9wICU+JQ0KICBtdXRhdGUoRC44X2xhYmVsID0gY2FzZV93aGVuKA0KICAgIEQuOCA9PSAiMSIgfiAiMS1wb3RlbnRpYWwgbG9zcyIsDQogICAgRC44ID09ICIyIiB+ICIyLXBvdGVudGlhbCBnYWluIiwNCiAgICBELjggPT0gIjMiIH4gIjMtcG90ZW50aWFsIGxvc3MgYW5kIGdhaW4gaGF2ZSB0aGUgc2FtZSBpbXBhY3QiDQogICkpDQojIGNhbGN1bGF0ZSBwcm9wb3J0aW9ucyB3aXRoaW4gZWFjaCBncm91cA0Kc3VydmV5X2Q4X3Byb3AgPC0gc3VydmV5X2Q4X3Byb3AgJT4lDQogIGdyb3VwX2J5KEdyb3VwKSAlPiUNCiAgbXV0YXRlKFByb3BvcnRpb24gPSBDb3VudCAvIHN1bShDb3VudCkpDQpnZ3Bsb3Qoc3VydmV5X2Q4X3Byb3AsIGFlcyh4ID0gYXMuZmFjdG9yKGBELjhfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+R3JvdXApKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkQuOCBBbnN3ZXIgUHJvcG90aW9uIFBsb3QgYWNyb3NzIEdyb3VwcyIsDQogICAgeCA9ICJSZXNwb25zZSIsDQogICAgeSA9ICJQcm9wb3J0aW9uIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KUGxvdCB0aGUgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCiMgaGlzdG9ncmFtIGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpnZ3Bsb3Qoc3VydmV5X2Q4LCBhZXMoeCA9IGQ4X3ZhbHVlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAid2hpdGUiKSArDQogICMgZmFjZXRfd3JhcCh+IGdyb3VwKSArDQogIGxhYnModGl0bGUgPSAiRC44IEhpc3RvZ3JhbSIsDQogICAgICAgeCA9ICJELjgiLA0KICAgICAgIHkgPSAiQ291bnQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHN1cnZleV9kOCRkOF92YWx1ZSwgbmEucm0gPSBUUlVFKSwgYnkgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojIyBELjkgRWZmZWN0aXZlbmVzcyBvZiB0aGUgZ3JhcGggZm9yIGRlY2lzaW9uLW1ha2luZw0KT24gYSBzY2FsZSBvZiAxIHRvIDEwLCB3aGVyZSAxIG1lYW5zIHRoZSBmb3JlY2FzdCB3YXMgbm90IGVmZmVjdGl2ZSBhdCBhbGwgYW5kIDEwIG1lYW5zIGl0IHdhcyB2ZXJ5IGVmZmVjdGl2ZSwgaG93IGVmZmVjdGl2ZSBkbyB5b3UgdGhpbmsgdGhlIGZvcmVjYXN0IHdhcyBpbiBhc3Npc3RpbmcgeW91ciBkZWNpc2lvbi1tYWtpbmc/XA0KKjEtTm90IGVmZmVjdGl2ZSBhdCBhbGw7IDEwLVZlcnkgZWZmZWN0aXZlKlwNClZhcmlhYmxlOiBjb250aW51b3VzXA0KTWV0aG9kOiBBTk5PVkEgdGVzdCBvciBLVyB0ZXN0IChkZXBlbmRzIG9uIHdoZXRoZXIgaXQncyBub3JtYWxseSBkaXN0cmlidXRlZClcDQoqKlJlc3VsdDogQXQgbGVhc3Qgb25lIGdyb3VwIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgdGhhbiBvdGhlcnMuICoqDQpgYGB7cn0NCiMgY29tYmluZSBkYXRhIGZyb20gZGlmZmVyZW50IGdyb3Vwcw0Kc3VydmV5X2Q5IDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X2Q5X2xpc3QgPC0gbGlzdCgiUTUuOV8xIiwiUTcuOV8xIiwgIlE5LjlfMSIsICJRMTEuOV8xIiwgIlExMy45XzEiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhncm91cF9saXN0KSkgew0KICBkZiA8LSBncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9kOV9saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygiZDlfdmFsdWUiLCAiZ3JvdXAiKQ0KICBzdXJ2ZXlfZDkgPC0gcmJpbmQoc3VydmV5X2Q5LCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X2Q5JGQ5X3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X2Q5JGQ5X3ZhbHVlKQ0KYGBgDQpTdGF0aXN0aWNhbCB0ZXN0DQpgYGB7cn0NCiMgSW5pdGlhbCBDaGVjaw0KIyBzdW1tYXJ5KHN1cnZleV9kOSRkOV92YWx1ZSkNCiMgY2hlY2sgbm9ybWFsaXR5IC0tPiB0aGUgZGF0YSBpcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQNCiMgc2hhcGlyby50ZXN0KHN1cnZleV9kOSRkOV92YWx1ZSkNCg0KIyBydW4gS3J1c2thbC1XYWxsaXMgdGVzdA0Ka3J1c2thbF90ZXN0IDwtIGtydXNrYWwudGVzdChkOV92YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X2Q5KQ0KcHJpbnQoa3J1c2thbF90ZXN0KQ0KIyBQb3N0LWhvYyB0ZXN0DQpkdW5uVGVzdChkOV92YWx1ZSB+IGdyb3VwLCBkYXRhID0gc3VydmV5X2Q5LCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQpgYGANClN1bW1hcnkgc3RhdGlzdGljcw0KYGBge3J9DQojIFN1bW1hcnkgc3RhdGlzdGljcw0Kc3VydmV5X2Q5X3N1bW1hcnkgPC0gc3VydmV5X2Q5ICU+JQ0KICBncm91cF9ieShncm91cCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuID0gbWVhbihkOV92YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBtZWRpYW4gPSBtZWRpYW4oZDlfdmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgc2QgPSBzZChkOV92YWx1ZSwgbmEucm0gPSBUUlVFKQ0KICApDQpgYGANCg0KUGxvdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGRpZmZlcmVudCBncm91cHMNCmBgYHtyfQ0KIyBHcm91cGVkIGJhci1zdHlsZSBoaXN0b2dyYW0NCmdncGxvdChzdXJ2ZXlfZDksIGFlcyh4ID0gZmFjdG9yKGQ5X3ZhbHVlKSwgZmlsbCA9IGZhY3Rvcihncm91cCkpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICAjIGZhY2V0X3dyYXAofiBncm91cCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkQuOSBUaGUgZGlzdHJpYnV0aW9uIG9mIGVmZmVjdGl2ZW5lc3Mgb2YgdGhlIGdyYXBoIGZvciBkZWNpc2lvbi1tYWtpbmcgYnkgZ3JvdXAiLA0KICAgIHggPSAiRC45IFJlc3BvbnNlIiwNCiAgICB5ID0gIkNvdW50IiwNCiAgICBmaWxsID0gIkdyb3VwIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIyA/IEQuMTIgU2tld2VkIEludmVzdG1lbnQgRGVjaXNpb24NCldoaWNoIGJvbmQgd291bGQgeW91IGNob29zZSB0byBpbnZlc3QgaW4/XA0KVmFyaWFibGU6IGNhdGVnb3JpY2FsXA0KTWV0aG9kOiBjb250aW5nZW5jeSB0YWJsZSAmIGNoaS1zcXVhcmVkIHRlc3RcDQoqKlJlc3VsdDogVGhlcmUgaXMgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBpbiBhdCBsZWFzdCBvbmUgZ3JvdXAuKioNCmBgYHtyfQ0KIyBjb21iaW5lIGRhdGEgZnJvbSBkaWZmZXJlbnQgZ3JvdXBzDQpzdXJ2ZXlfZDEyIDwtIGRhdGEuZnJhbWUoKQ0Kc3VydmV5X2QxMl9saXN0IDwtIGxpc3QoIlE3LjEyIiwgIlE5LjEyIiwgIlExMS4xMiIsICJRMTMuMTIiKQ0KZm9yIChpIGluIHNlcV9hbG9uZyhza2V3ZWRfZ3JvdXBfbGlzdCkpIHsNCiAgZGYgPC0gc2tld2VkX2dyb3VwX2xpc3RbW2ldXQ0KICBjb2wgPC0gc3VydmV5X2QxMl9saXN0W1tpXV0NCiAgdGVtcF90YWJsZSA8LSBkZlssIGMoY29sLCAiZ3JvdXAiKV0NCiAgbmFtZXModGVtcF90YWJsZSkgPC0gYygiZDEyX3ZhbHVlIiwgImdyb3VwIikNCiAgc3VydmV5X2QxMiA8LSByYmluZChzdXJ2ZXlfZDEyLCB0ZW1wX3RhYmxlKQ0KfQ0Kc3VydmV5X2QxMiRkMTJfdmFsdWUgPC0gYXMubnVtZXJpYyhzdXJ2ZXlfZDEyJGQxMl92YWx1ZSkNCmBgYA0KQ29udGluZ2VuY3kgdGFibGUNCmBgYHtyfQ0Kc3VydmV5X2QxMl9jb250aW5nZW5jeSA8LSB0YWJsZShzdXJ2ZXlfZDEyJGQxMl92YWx1ZSwgc3VydmV5X2QxMiRncm91cCkNCnByaW50KHN1cnZleV9kMTJfY29udGluZ2VuY3kpDQojIHJ1biBjaGktc3F1YXJlZCB0ZXN0DQpjaGlzcV9yZXN1bHQgPC0gY2hpc3EudGVzdChzdXJ2ZXlfZDEyX2NvbnRpbmdlbmN5KQ0KIyBwcmludChjaGlzcV9yZXN1bHQpDQpzdGRfcmVzaWQgPC0gY2hpc3FfcmVzdWx0JHN0ZHJlcw0KcHJpbnQoc3RkX3Jlc2lkKQ0KDQojIHBhaXJ3aXNlIHByb3BvcnRpb24gdGVzdA0KcGFpcndpc2UucHJvcC50ZXN0KA0KICB4ID0gc3VydmV5X2QxMl9jb250aW5nZW5jeVsyLF0sDQogIG4gPSBjb2xTdW1zKHN1cnZleV9kMTJfY29udGluZ2VuY3kpLA0KICBwLmFkanVzdC5tZXRob2QgPSAiYm9uZmVycm9uaSIgIyBvciAiaG9sbSIsICJCSCINCikNCmBgYA0KUGxvdCBwcm9wb3J0aW9uIGJhciBwbG90IGFjcm9zcyBkaWZmZXJlbnQgZ3JvdXBzDQpgYGB7cn0NCnN1cnZleV9kMTJfcHJvcCAgPC0gYXMuZGF0YS5mcmFtZShzdXJ2ZXlfZDEyX2NvbnRpbmdlbmN5KQ0KIyByZW5hbWUgY29sdW1ucw0KbmFtZXMoc3VydmV5X2QxMl9wcm9wKSA8LSBjKCJELjEyIiwgIkdyb3VwIiwgIkNvdW50IikNCiMgYWRkIGEgbGFiZWxsZWQgY29sdW1uDQpzdXJ2ZXlfZDEyX3Byb3AgPC0gc3VydmV5X2QxMl9wcm9wICU+JQ0KICBtdXRhdGUoRC4xMl9sYWJlbCA9IGNhc2Vfd2hlbigNCiAgICBELjEyID09ICIxIiB+ICJBLiBOb21pbmFsIEJvbmQiLA0KICAgIEQuMTIgPT0gIjIiIH4gIkIuIEluZmxhdGlvbi1Qcm90ZWN0ZWQgQm9uZCINCiAgKSkNCiMgY2FsY3VsYXRlIHByb3BvcnRpb25zIHdpdGhpbiBlYWNoIGdyb3VwDQpzdXJ2ZXlfZDEyX3Byb3AgPC0gc3VydmV5X2QxMl9wcm9wICU+JQ0KICBncm91cF9ieShHcm91cCkgJT4lDQogIG11dGF0ZShQcm9wb3J0aW9uID0gQ291bnQgLyBzdW0oQ291bnQpKQ0KZ2dwbG90KHN1cnZleV9kMTJfcHJvcCwgYWVzKHggPSBhcy5mYWN0b3IoYEQuMTJfbGFiZWxgKSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBHcm91cCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogICMgZmFjZXRfd3JhcCh+R3JvdXApKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkQuMTIgQW5zd2VyIFByb3BvdGlvbiBQbG90IGFjcm9zcyBHcm91cHMiLA0KICAgIHggPSAiUmVzcG9uc2UiLA0KICAgIHkgPSAiUHJvcG9ydGlvbiINCiAgKSArDQogICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQpgYGANClBsb3QgcGllIGNoYXJ0IGluY2x1ZGluZyBhbGwgcGFydGljaXBhbnRzDQpgYGB7cn0NCnN1cnZleV9kMTJfc3VtbWFyeSA8LSBzdXJ2ZXlfZDEyX3Byb3AgJT4lDQogIGdyb3VwX2J5KGBELjEyX2xhYmVsYCkgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9jb3VudCA9IHN1bShDb3VudCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBtdXRhdGUocHJvcG9ydGlvbiA9IHRvdGFsX2NvdW50IC8gc3VtKHRvdGFsX2NvdW50KSwNCiAgICAgICAgIGBELjEyX2dyYXBoX2xhYmVsYCA9IHBhc3RlMChgRC4xMl9sYWJlbGAsICIgKCIsIHJvdW5kKHByb3BvcnRpb24gKiAxMDAsIDIpLCAiICUpIikpDQpnZ3Bsb3Qoc3VydmV5X2QxMl9zdW1tYXJ5LCBhZXMoeCA9ICIiLHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gYEQuMTJfZ3JhcGhfbGFiZWxgKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgbGFicyh0aXRsZSA9ICJELjEyIEludmVzdG1lbnQgRGVjaXNpb24gU3VtbWFyeSBQaWUgQ2hhcnQiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCiMjIEQuMTMgU2tld2VkIENvbmZpZGVudGNlIGluIGRlY2lzaW9uLW1ha2luZw0KT24gYSBzY2FsZSBvZiAxIHRvIDEwLCB3aGVyZSAxIG1lYW5zIG5vdCBjb25maWRlbnQgYXQgYWxsIGFuZCAxMCBtZWFucyB2ZXJ5IGNvbmZpZGVudCwgaG93IGNvbmZpZGVudCAgYXJlIHlvdSBpbiBtYWtpbmcgdGhlIGRlY2lzaW9uP1wNCioxLU5vdCBjb25maWRlbnQgYXQgYWxsOyAxMC1WZXJ5IGNvbmZpZGVudCpcDQpWYXJpYWJsZTogY29udGludW91c1wNCk1ldGhvZDogQU5OT1ZBIHRlc3Qgb3IgS1cgdGVzdCAoZGVwZW5kcyBvbiB3aGV0aGVyIGl0J3Mgbm9ybWFsbHkgZGlzdHJpYnV0ZWQpXA0KKipSZXN1bHQ6IEF0IGxlYXN0IG9uZSBncm91cCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IHRoYW4gb3RoZXJzLiAqKg0KYGBge3J9DQojIGNvbWJpbmUgZGF0YSBmcm9tIGRpZmZlcmVudCBncm91cHMNCnN1cnZleV9kMTMgPC0gZGF0YS5mcmFtZSgpDQpzdXJ2ZXlfZDEzX2xpc3QgPC0gbGlzdCgiUTcuMTNfMSIsICJROS4xM18xIiwgIlExMS4xM18xIiwgIlExMy4xM18xIikNCmZvciAoaSBpbiBzZXFfYWxvbmcoc2tld2VkX2dyb3VwX2xpc3QpKSB7DQogIGRmIDwtIHNrZXdlZF9ncm91cF9saXN0W1tpXV0NCiAgY29sIDwtIHN1cnZleV9kMTNfbGlzdFtbaV1dDQogIHRlbXBfdGFibGUgPC0gZGZbLCBjKGNvbCwgImdyb3VwIildDQogIG5hbWVzKHRlbXBfdGFibGUpIDwtIGMoImQxM192YWx1ZSIsICJncm91cCIpDQogIHN1cnZleV9kMTMgPC0gcmJpbmQoc3VydmV5X2QxMywgdGVtcF90YWJsZSkNCn0NCnN1cnZleV9kMTMkZDEzX3ZhbHVlIDwtIGFzLm51bWVyaWMoc3VydmV5X2QxMyRkMTNfdmFsdWUpDQpgYGANClN0YXRpc3RpY2FsIHRlc3QNCmBgYHtyfQ0KIyBJbml0aWFsIENoZWNrDQojIHN1bW1hcnkoc3VydmV5X2QxMyRkMTNfdmFsdWUpDQojIGNoZWNrIG5vcm1hbGl0eSAtLT4gdGhlIGRhdGEgaXMgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkDQojIHNoYXBpcm8udGVzdChzdXJ2ZXlfZDEzJGQxM192YWx1ZSkNCg0KIyBydW4gS3J1c2thbC1XYWxsaXMgdGVzdA0Ka3J1c2thbF90ZXN0IDwtIGtydXNrYWwudGVzdChkMTNfdmFsdWUgfiBncm91cCwgZGF0YSA9IHN1cnZleV9kMTMpDQpwcmludChrcnVza2FsX3Rlc3QpDQoNCmBgYA0KU3VtbWFyeSBzdGF0aXN0aWNzDQpgYGB7cn0NCiMgU3VtbWFyeSBzdGF0aXN0aWNzDQpzdXJ2ZXlfZDEzX3N1bW1hcnkgPC0gc3VydmV5X2QxMyAlPiUNCiAgZ3JvdXBfYnkoZ3JvdXApICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbiA9IG1lYW4oZDEzX3ZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgIG1lZGlhbiA9IG1lZGlhbihkMTNfdmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgc2QgPSBzZChkMTNfdmFsdWUsIG5hLnJtID0gVFJVRSkNCiAgKQ0KYGBgDQpQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IGdyb3Vwcw0KYGBge3J9DQojIEdyb3VwZWQgYmFyLXN0eWxlIGhpc3RvZ3JhbQ0KZ2dwbG90KHN1cnZleV9kMTMsIGFlcyh4ID0gZmFjdG9yKGQxM192YWx1ZSksIGZpbGwgPSBmYWN0b3IoZ3JvdXApKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgIyBmYWNldF93cmFwKH4gZ3JvdXApICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJELjEzIFRoZSBkaXN0cmlidXRpb24gb2YgY29uZmlkZW5jZSBpbiBkZWNpc2lvbi1tYWtpbmcgYnkgZ3JvdXAiLA0KICAgIHggPSAiRC4xMyBSZXNwb25zZSIsDQogICAgeSA9ICJDb3VudCIsDQogICAgZmlsbCA9ICJHcm91cCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KIyBDcm9zcy10YWJ1bGF0aW9uDQojIyBDdXJyZW50IEluZmxhdGlvbiBLbm93bGVkZ2UgdnMuIEluZmxhdGlvbiBGb3JlY2FzdCBLbm93bGVkZ2UNCiMjIFNrZXdlZCBEYXRhIHZzLiBVbnNrZXdlZCBEYXRhICggdW5kZXJzdGFuZGluZyBhbmQgZGVjaXNpb24gbWFraW5nKQ0KIyMgRm9yIHBlb3BsZSB3aG8gY2FuIGNvcnJlY3RseSB1bmRlcnN0YW5kIHRoZSBwcm9iYWJpbGl0eSAoPyB3aGljaCksIHdoYXQgZGVjaXNpb24gZG8gdGhleSBtYWtlPyAtLT4gSSBhbSB0aGlua2luZyBwcm9wb3Rpb24gdGVzdCBzZWUgcmVkdWNlZCBwcm9iYWJpbGl0eS4gDQojIyBEb2VzIGZhbWlsYXJpdHkgd2l0aCB0aGUgZ3JhcGggdHlwZSBhZmZlY3QgdW5kZXJzdGFuZGluZyBhbmQgdGhlIGRlY2lzaW9uPw0KDQoNCg0KIyBTdGF0aXN0aWNhbCBUZXN0aW5nIDxhIG5hbWU9InN0YXRpc3RpY2FsLXRlc3RpbmciPjwvYT4NCiMjIEJhc2ljcw0KVHlwZSBJIGVycm9yLSBmYWxzZSBwb3NpdGl2ZXMgKHNheWluZyB0aGVyZSdzIGEgZGlmZmVyZW5jZSB3aGVuIHRoZXJlIGlzbid0KQ0KIyMgQ2hpLXNxdWFyZWQgdGVzdA0KIyMjIFBvc3QtaG9jIHRlc3QNCjEuIFN0YW5kYXJkaXplZCByZXNpZHVhbHMNCmBgYHtyfQ0KY2hpc3FfcmVzdWx0IDwtIGNoaXNxLnRlc3QocTNfNF9jb250aW5nZW5jeSkNCnN0ZF9yZXNpZCA8LSBjaGlzcV9yZXN1bHQkc3RkcmVzDQpwcmludChzdGRfcmVzaWQpDQpgYGANCkNlbGxzIHdpdGggYWJzb2x1dGUgdmFsdWUgPiB+MiAob3IgPiAxLjk2IGZvciA5NSUgY29uZmlkZW5jZSlpbmRpY2F0ZSAgY29udHJpYnV0aW5nIG1vc3QgdG8gdGhlIG92ZXJhbGwgY2hpLXNxdWFyZWRcDQoNCjIuIFBhaXJ3aXNlIHByb3BvcnRpb24gdGVzdHM6IGNhbiBvbmx5IGNvbXBhcmUgb25lIHZhbHVlDQpgYGB7cn0NCnBhaXJ3aXNlLnByb3AudGVzdCgNCiAgeCA9IHEzXzRfY29udGluZ2VuY3lbLCAxOm5jb2wocTNfNF9jb250aW5nZW5jeSldLCAgIyBjb3VudHMgcGVyIGdyb3VwDQogIG4gPSBjb2xTdW1zKHEzXzRfY29udGluZ2VuY3kpLCAgICAgICAgICAgICAgICAgICAgICMgdG90YWwgcGVyIGdyb3VwDQogIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiAgICAgICAgICAgICAgICAgICAgICMgb3IgImhvbG0iLCAiQkgiDQopDQpgYGANCg0KDQojIyBBTk9WQSB0ZXN0DQpBTk9WQSBvbmx5IGNvbXBhcmVzIHRoZSBtZWFucyBvZiB0aGUgZ3JvdXBzLlwNCiMjIyBBc3N1bXB0aW9ucyBvZiBBTk9WQQ0KMS4gTm9ybWFsaXR5IG9mIHJlc2lkdWFscyB3aXRoaW4gZWFjaCBncm91cDogSWYgcC12YWx1ZTwwLjA1LCB0aGUgZGF0YSBpcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWRcDQpgYGB7cn0NCnNoYXBpcm8udGVzdChkZiR2YWx1ZSkNCmBgYA0KDQoyLiBIb21vZ2VuZWl0eSBvZiB2YXJpYW5jZXMgYWNyb3NzIGdyb3Vwcw0KYGBge3J9DQojIENoZWNrIHRoZSBhc3N1bXB0aW9uIG9mIGVxdWFsIHZhcmlhbmNlcyAoaG9tb2dlbmVpdHkgb2YgdmFyaWFuY2UpIGFjcm9zcyBncm91cHMgDQojIElmIHA8IDAuMDUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBvZiBlcXVhbCB2YXJpYW5jZXMsIG1lYW5pbmcgdGhlIHZhcmlhbmNlcyBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYWNyb3NzIGdyb3Vwcw0KYmFydGxldHQudGVzdChgUTMuMmAgfiBncm91cCwgZGF0YSA9IGFnZV90YWJsZSkgIyBpZiBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkDQojIExldmVuZSdzIHRlc3QgZm9yIGhvbW9nZW5laXR5IG9mIHZhcmlhbmNlIGlmIGRhdGEgbWF5IG5vdCBiZSBub3JtYWxseSBkaXN0cmlidXRlZA0KbGlicmFyeShjYXIpDQpsZXZlbmVUZXN0KHZhbHVlIH4gZ3JvdXAsIGRhdGEgPSB0aW1lX2R1cmF0aW9uX3RhYmxlKQ0KYGBgDQojIyMgUG9zdC1ob2MgdGVzdA0KSWYgQU5PVkEgaXMgc2lnbmlmaWNhbnQsIHdlIGNhbiBwZXJmb3JtIHBvc3QtaG9jIHRlc3RzIHRvIGRldGVybWluZSB3aGljaCBncm91cHMgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gZWFjaCBvdGhlci5cDQpgYGB7cn0NCiMgcG9zdC1ob2MgdGVzdA0KdHVrZXlfdGVzdCA8LSBUdWtleUhTRChhbm92YV90ZXN0KQ0KcHJpbnQodHVrZXlfdGVzdCkNCg0KYGBgDQoNCj4gTnVsbCBoeXBvdGhlc2lzIChI4oKAKTogQWxsIGdyb3VwIG1lYW5zIGFyZSBlcXVhbFwNCj4gQWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyAoSOKCgSk6IEF0IGxlYXN0IG9uZSBncm91cCBtZWFuIGlzIGRpZmZlcmVudA0KDQojIyBLcnVza2FsLVdhbGxpcyB0ZXN0DQoobm9uLXBhcmFtZXRyaWMgdGVzdClcDQp3aGVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgaXMgY29udGludW91cyBvciBvcmRpbmFsXA0Kd2hlbiB0aGUgYXNzdW1wdGlvbnMgb2Ygb25lLXdheSBBTk9WQSBhcmUgbm90IG1ldDogbm9ybWFsaXR5IGFuZCBlcXVhbCB2YXJpYW5jZXMNCg0KZS5nLiwgTGlrZXJ0LXNjYWxlIHJlc3BvbnNlcyAob3JkaW5hbCkgDQojIyMgUG9zdC1ob2MgdGVzdA0KYGBge3J9DQpsaWJyYXJ5KEZTQSkNCg0KZHVublRlc3QodmFsdWUgfiBncm91cCwgZGF0YSA9IGRmLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQojIA0KYGBgDQoNCiMjIFByb3BvdGlvbiB0ZXN0IC1wcm9wLnRlc3QoKQ0KLSBwcm9wLnRlc3QoKTogYXQgbGVhc3Qgb25lIGdyb3VwIGRpZmZlcnMNCjxmb250IGNvbG9yPSJyZWQiPmNvbnRpbnVpdHkgY29ycmVjdGlvbj8/PC9mb250Pg0KVGhlIHByb3AudGVzdCgpIGZ1bmN0aW9uIG9ubHkgc3VwcG9ydHMgYWx0ZXJuYXRpdmUgPSAibGVzcyIgb3IgImdyZWF0ZXIiIHdoZW4gY29tcGFyaW5nIGEgc2luZ2xlIHByb3BvcnRpb24gdG8gYSBoeXBvdGhlc2l6ZWQgdmFsdWUg4oCUIG5vdCB3aGVuIGNvbXBhcmluZyBtdWx0aXBsZSBncm91cHMuDQotIHBhaXJ3aXNlLnByb3AudGVzdCgpOiAgaWRlbnRpZnlpbmcgd2hpY2ggc3BlY2lmaWMgcGFpcnMgb2YgZ3JvdXBzIGRpZmZlciBzaWduaWZpY2FudGx5IGluIHRoZWlyIHByb3BvcnRpb25zLCBjaG9vc2UgdGhlIHAuYWRqdXN0Lm1ldGhvZCA9ICJob2xtIiBvciAiYm9uZmVycm9uaSIgb3IgIkJIIg0K